home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-04-10 | 99.3 KB | 3,884 lines | [TEXT/MPS ] |
- // Experiment no.9
- //
- // Fast food code to check out various printing operations.
- //
- // This application contains routines that exercise nearly every part
- // of the QuickDraw GX printing API-- from handling the modified 'pdoc'
- // AppleEvents or properly servicing resume events, to adding a panel in
- // the "Page Setup" dialog or reading pages from a print file. For the
- // most part, the code in this file is "ungroomed," but it's still useful
- // if you're trying to figure out how to take advantage of a particular
- // GX printing feature.
- //
- // All routines are listed in MPW's Mark menu, to make it easy to find the
- // code you're looking for. For example, if you were trying to figure out
- // how to flatten a gxJob into your document's data fork, you'd go to the
- // routine listed as "MySaveJobInDataFork" in the Mark menu.
- //
- // If you don't see a marked routine that looks like what you're after, try
- // searching for the specific GX routine you're interested in. Some routines
- // in this file, (like the saving routines), do a lot more than their names
- // may imply. And, note that not all of the routines in this file are used
- // by the built application. For example, none of the routines which get
- // format mappings are used, since they don't do anything visible. Also,
- // there are 4 different print routines, 3 different open routines, and 2
- // different saving routines. Only one of each is used by the built app.
- // If you change which ones are used, make sure that the opening and saving
- // routines agree with each other. If the open routine expects to load a
- // saved job from a document's data fork, make sure that you aren't using
- // the routine which saves the job in the resource fork.
- //
- // This application has been thrown together very roughly, and is meant to
- // be a functioning "container" for the print code snippets that an application
- // developer is most likely to want. The Inside Mac printing samples were
- // written in this application, so much of what appears here also appears in
- // Inside Mac.
- //
- // 4/26/93 - dmh - Thrown on the grill.
- // 9/10/93 - dmh - Updated for b2.
- // Neutralized some nasty bugs.
- // 12/18/93 - dmh - Updated for b3.
- // 2/03/94 - dmh - Made "square resolution" in
- // MyGetFormatDeviceResolution really square.
- // 3/22/94 - dmh - Added page range code (only enable for f2c1.2 or later!!).
- // 3/22/94 - dmh - Added "print one copy" code.
- // 3/22/94 - dmh - Added code to retrieve the formatting printers profiel and colorSpace.
- // 3/22/94 - dmh - Cleaned up(?) the Mark menu.
- // 3/22/94 - dmh - Updated for b4.
- // 3/24/94 - dmh - general cleanup and debugging.
- // 5/3/94 - dmh - …more of the same for f2.
- // 7/13/94 - dmh - Enabled printer resolution code.
- // 8/24/94 - dmh - Universalized.
- //
-
- #include "Experiment no.9.h"
- #include "GXExceptions.h"
-
- Boolean gQuitting; // Quitting?
- MyDocumentRec myDocument; // Our document.
- short gAppResRefNum; // Our application's resource file refNum.
- Boolean gInPrintDialog; // Currently in a print dialog?
- RgnHandle gCursorRgn; // Mouse region used by WaitNextEvent.
-
- // This routine initializes everything for our application.
-
- OSErr MyInitializeApp()
- {
- OSErr err = noErr;
- Handle menuBar;
-
- gQuitting = false;
- gInPrintDialog = false;
-
- InitGraf((Ptr) &qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- InitCursor();
- FlushEvents(everyEvent, 0);
-
- gAppResRefNum = CurResFile();
- gCursorRgn = NewRgn();
-
-
- // Create and set up the menubar.
-
- menuBar = GetNewMBar(r_menuBar);
- SetMenuBar(menuBar);
- DisposHandle(menuBar);
- AddResMenu(GetMHandle(mApple), 'DRVR');
- MyAdjustMenus();
- DrawMenuBar();
-
- MyAEInstallation();
-
- return err;
- }
-
-
- // This routine installs our core AppleEvent handlers.
-
- void MyAEInstallation()
- {
- AEInstallEventHandler(kCoreEventClass,
- kAEOpenApplication,
- NewAEEventHandlerProc(MyHandleOAPP),
- 0, false);
-
- AEInstallEventHandler(kCoreEventClass,
- kAEQuitApplication,
- NewAEEventHandlerProc(MyHandleQUIT),
- 0, false);
-
- AEInstallEventHandler(kCoreEventClass,
- kAEOpenDocuments,
- NewAEEventHandlerProc(MyHandleODOC),
- 0, false);
-
- AEInstallEventHandler(kCoreEventClass,
- kAEPrintDocuments,
- NewAEEventHandlerProc(MyHandlePDOC),
- 0, false);
- }
-
-
- // This is the "open application" AppleEvent handler. We don't
- // do anything more than check out the message.
-
- pascal OSErr MyHandleOAPP(AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon)
- {
-
- #pragma unused (reply, myRefCon)
-
- return MyCheckAEParams(theAppleEvent);
- }
-
-
- // This is the "quit" AppleEvent handler. Set the gQuitting and
- // the event loop will do the rest.
-
- pascal OSErr MyHandleQUIT(AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon)
- {
- OSErr err;
-
- #pragma unused (reply, myRefCon)
-
- err = MyCheckAEParams(theAppleEvent);
- if (err) return err;
-
- gQuitting = true;
- return noErr;
- }
-
-
- // This is the "open document" AppleEvent handler.
-
- pascal OSErr MyHandleODOC(AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon)
- {
- OSErr err;
- AEDescList docList;
- FSSpec myFSS;
- AEKeyword theKeyword;
- DescType typeCode;
- Size actualSize;
-
- #pragma unused (reply, myRefCon)
-
- // Get our doc list.
-
- err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &docList);
- if (err) return err;
-
- err = MyCheckAEParams(theAppleEvent);
- if (err) return err;
-
-
- // Open the first entry in the document list. This app only handles one
- // document at a time, so if we are trying to open a second, don't.
-
- err = AEGetNthPtr(&docList, 1, typeFSS, &theKeyword, &typeCode,
- (Ptr) &myFSS, sizeof(FSSpec), &actualSize);
-
- AEDisposeDesc(&docList);
-
- if (err || (FrontWindow() != nil)) return err;
-
- err = MyNewDocument("\pUntitled", &myDocument);
-
- if (err == noErr)
- {
- err = MyFSOpenDocument(&myDocument, &myFSS);
-
- if (err == noErr)
- ShowWindow(myDocument.documentWindow);
- }
-
- if (err != noErr) MyCloseDocument(&myDocument);
-
- return err;
- }
-
-
- // This is our "print document" AppleEvent handler. It handles files printed
- // with the Finder's 'Print' command, as well as those dragged to desktop
- // printers.
-
- pascal OSErr MyHandlePDOC(AppleEvent *theAppleEvent, AppleEvent *reply, long myRefCon)
- {
- OSErr err;
- AEDescList docList, dtpList;
- FSSpec myFSS, dtpFSS;
- long itemsInList, i;
- AEKeyword theKeyword;
- DescType typeCode;
- Boolean draggedToDTP = false;
- Size actualSize;
-
- #pragma unused (reply, myRefCon)
-
- // Get our document list.
-
- err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &docList);
- if (err) return err;
-
-
- // See if the document was dragged to a desktop printer.
-
- err = AEGetAttributeDesc(theAppleEvent, keyOptionalKeywordAttr, typeAEList, &dtpList);
- if (err == noErr) draggedToDTP = true;
-
-
- // Make sure we've accounted for all of the parameters passed, and count the
- // number of documents passed in.
-
- err = MyCheckAEParams(theAppleEvent);
- if (err) return err;
-
- err = AECountItems(&docList, &itemsInList);
- if (err) return err;
-
-
- // If we dragged to a desktop printer, get the name of the desktop printer
- // and then throw away the description list for it.
-
- if (draggedToDTP)
- {
- err = AEGetNthPtr(&dtpList, 1, typeFSS, &theKeyword, &typeCode,
- (Ptr) &dtpFSS, sizeof(FSSpec), &actualSize);
-
- AEDisposeDesc(&dtpList);
- }
-
- // For each entry in the document list, load it, print it, and close it.
-
- for (i = 1; i<= itemsInList, err == noErr; i++)
- {
- err = AEGetNthPtr(&docList, i, typeFSS, &theKeyword, &typeCode,
- (Ptr) &myFSS, sizeof(FSSpec), &actualSize);
-
- if (err == noErr)
- {
-
- // Load the document.
-
- err = MyNewDocument("\p", &myDocument);
-
- if (err == noErr)
- {
- err = MyFSOpenDocument(&myDocument, &myFSS);
-
-
- // If we dragged to a desktop printer, select that as the output printer for
- // each job and only print one copy. Otherwise, present the dialogs so that
- // the user can set things up.
-
- if (err == noErr)
- {
- if (draggedToDTP)
- {
- GXSelectJobOutputPrinter(myDocument.documentJob, dtpFSS.name);
- err = MyPrintOneCopy(&myDocument);
- }
- else
- err = MyPrintDocument(&myDocument);
- }
-
- // Close the document once it's printed.
-
- MyCloseDocument(&myDocument);
- }
- }
- }
-
- // When we're all done throw away the document list.
-
- AEDisposeDesc(&docList);
- return err;
- }
-
-
- // MyCheckAEParams - This routine is used to make sure we've
- // received all the parameters for an AppleEvent. If so, we
- // return noErr, otherwise we indicate that the event wasn't
- // handled completely.
-
- OSErr MyCheckAEParams(AppleEvent *theAppleEvent)
- {
- OSErr err;
- DescType typeCode;
- Size actualSize;
-
- err = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr,
- typeWildCard, &typeCode, nil, 0, &actualSize);
-
- if (err == errAEDescNotFound) return noErr;
- if (err == noErr) return errAEEventNotHandled;
-
- return err;
- }
-
-
- // Our event loop routine.
-
- void MyEventLoop()
- {
- Boolean gotEvent;
- EventRecord event;
- long sleepTime;
-
- // While not quitting, repeatedly get and dispatch events. Sleep
- // an appropriate amount whether we're running in the foreground
- // or background. Every time through we unload all our segments.
- // They won't actually be purged unless we need the memory.
-
- while (!gQuitting)
- {
- sleepTime = GetDblTime();
- gotEvent = WaitNextEvent(everyEvent, &event, sleepTime, gCursorRgn);
-
- if (gotEvent)
- MyDoEvent(&event);
- }
- }
-
-
- // This routine handles whatever events come our way.
-
- OSErr MyDoEvent(EventRecord *event)
- {
- OSErr err = noErr;
- short windowPart;
- WindowPtr window;
- char key;
- Point mountPoint;
- Rect dragRect;
- RgnHandle grayRgn;
- WindowPtr curWindow;
- MyDocumentPtr windowDoc;
-
- // Set up a rectangle to use for dragging windows around. Then,
- // handle any events.
-
- grayRgn = GetGrayRgn();
- dragRect = (*grayRgn)->rgnBBox;
-
- switch (event->what)
- {
- case mouseDown:
- windowPart = FindWindow(event->where, &window);
- switch (windowPart)
- {
- case inMenuBar:
- MyAdjustMenus();
- MyDoMenuCommand(MenuSelect(event->where));
- break;
-
- case inContent:
- if (window != FrontWindow())
- SelectWindow(window);
- break;
-
- case inDrag:
- DragWindow(window, event->where, &dragRect);
- break;
-
- case inGoAway:
- if (TrackGoAway(window, event->where))
- {
- err = MyCloseDocument(&myDocument);
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyCloseDocument!", err);
- MyDisplayInfo(pStr);
- }
- }
- break;
- }
- break;
-
- case mouseMovedMessage:
- DisposeRgn(gCursorRgn); /* get rid of old region */
- gCursorRgn = NewRgn();
- SetRectRgn(gCursorRgn, -32768, -32768, 32766, 32766);
- break;
-
- case keyDown:
- case autoKey:
- key = event->message & charCodeMask;
- if (event->modifiers & cmdKey)
- if (event->what == keyDown)
- {
- MyAdjustMenus();
- MyDoMenuCommand(MenuKey(key));
- }
- break;
-
- case updateEvt:
- MyWindowUpdate((WindowPtr) event->message);
- break;
-
- case diskEvt:
- if ((event->message >> 16) != noErr)
- {
- mountPoint.h = 100;
- mountPoint.v = 100;
- err = DIBadMount(mountPoint, event->message);
- }
- break;
-
- case osEvt:
- switch ((event->message >> 24) & 0x0FF)
- {
- case suspendResumeMessage:
-
- SetCursor(&qd.arrow);
-
- // Suspend event:
- //
- // On a suspend event, just coerce the scrap.
-
- if ((event->message & resumeFlag) == 0)
- {
- ZeroScrap();
- TEToScrap();
- }
- else
- {
-
- // Resume event:
- //
- // On a resume event, we need to call UpdateJob on all of our documents'
- // jobs. This is important because the user may have just changed
- // something which affects our jobs (like the size of the paper in the
- // printer).
- //
- // Since our application stores our document pointers in the refCon fields
- // of our documents' windows, we just loop through every one of our windows,
- // extract our document pointers and update the associated jobs.
-
- if (event->message & convertClipboardFlag)
- TEFromScrap();
-
- curWindow = FrontWindow();
-
- while (curWindow != nil)
- {
- if (((WindowPeek) curWindow)->windowKind == userKind)
- {
- windowDoc = (MyDocumentPtr) GetWRefCon(curWindow);
- GXUpdateJob(windowDoc->documentJob);
- }
-
- curWindow = (WindowPtr) ((WindowPeek) curWindow)->nextWindow;
- }
- }
- break;
- }
- break;
-
- case kHighLevelEvent:
- AEProcessAppleEvent(event);
- break;
- }
-
- return err;
- }
-
-
- // This routine handles enabling and disabling menu items as
- // required by the current context.
-
- void MyAdjustMenus()
- {
- WindowPtr wp;
- MenuHandle fileMenu, editMenu, testMenu;
- MyDocumentPtr myDocument;
- Boolean docOpen, hasPages, onFirstPage, onLastPage, maxPages, neverSaved;
-
- if (gInPrintDialog) return;
-
- editMenu = GetMHandle(mEdit);
- fileMenu = GetMHandle(mFile);
- testMenu = GetMHandle(mTest);
-
- EnableItem(fileMenu, kQuit);
- EnableItem(testMenu, kGetFileNumPages);
-
-
- // If we have a window open, we enable certain menu items,
- // otherwise we don't.
-
- wp = FrontWindow();
-
- if (((WindowPeek) wp)->windowKind != userKind)
- wp = nil;
-
- docOpen = (wp != nil);
-
- if (!docOpen)
- {
- EnableItem(fileMenu, kNew);
- EnableItem(fileMenu, kOpen);
- DisableItem(fileMenu, kClose);
- DisableItem(fileMenu, kSave);
- DisableItem(fileMenu, kSaveAs);
- DisableItem(fileMenu, kInsertPage);
- DisableItem(fileMenu, kDeletePage);
- DisableItem(fileMenu, kPrint);
- DisableItem(fileMenu, kPrintOne);
- DisableItem(fileMenu, kPageSetup);
- DisableItem(fileMenu, kDocSetup);
- EnableItem(fileMenu, kQuit);
- DisableItem(testMenu, kAheadPage);
- DisableItem(testMenu, kBackPage);
- DisableItem(testMenu, kAddForm);
- DisableItem(testMenu, kRemoveForm);
- DisableItem(testMenu, kApplyAboveFormat);
- DisableItem(testMenu, kGetCopiesInfo);
- DisableItem(testMenu, kShowJobPrinterInfo);
- DisableItem(testMenu, kJobRefConTest);
- DisableItem(testMenu, kReadFilePage);
- DisableItem(testMenu, kGetPaperTypeName);
- DisableItem(testMenu, kGetPaperDimensions);
- DisableItem(testMenu, kGetAllPaperTypeInfo);
- DisableItem(testMenu, kShowPrinterResolution);
- }
- else
- {
- DisableItem(fileMenu, kNew);
- DisableItem(fileMenu, kOpen);
- EnableItem(fileMenu, kClose);
- EnableItem(fileMenu, kDocSetup);
- EnableItem(testMenu, kGetCopiesInfo);
- EnableItem(testMenu, kShowJobPrinterInfo);
- EnableItem(testMenu, kJobRefConTest);
- EnableItem(testMenu, kShowPrinterResolution);
-
- myDocument = (MyDocumentPtr) GetWRefCon(wp);
-
- hasPages = (myDocument->numPages != 0);
- onFirstPage = (myDocument->curPage == 1);
- onLastPage = (myDocument->curPage == myDocument->numPages);
- maxPages = (myDocument->numPages == kMaxPages);
- neverSaved = (myDocument->documentFSSpec.name[0] == 0);
-
- if (neverSaved || !hasPages)
- DisableItem(fileMenu, kSave);
- else
- EnableItem(fileMenu, kSave);
-
- if (!maxPages)
- EnableItem(fileMenu, kInsertPage);
- else
- DisableItem(fileMenu, kInsertPage);
-
- if (hasPages)
- {
- EnableItem(fileMenu, kSaveAs);
- EnableItem(fileMenu, kDeletePage);
- EnableItem(fileMenu, kPrintOne);
- EnableItem(fileMenu, kPageSetup);
- EnableItem(fileMenu, kPrint);
- EnableItem(testMenu, kAddForm);
- EnableItem(testMenu, kRemoveForm);
- EnableItem(testMenu, kReadFilePage);
- EnableItem(testMenu, kGetPaperTypeName);
- EnableItem(testMenu, kGetPaperDimensions);
- EnableItem(testMenu, kGetAllPaperTypeInfo);
- }
- else
- {
- DisableItem(fileMenu, kSaveAs);
- DisableItem(fileMenu, kDeletePage);
- DisableItem(fileMenu, kPrintOne);
- DisableItem(fileMenu, kPageSetup);
- DisableItem(fileMenu, kPrint);
- DisableItem(testMenu, kAddForm);
- DisableItem(testMenu, kRemoveForm);
- DisableItem(testMenu, kReadFilePage);
- DisableItem(testMenu, kGetPaperTypeName);
- DisableItem(testMenu, kGetPaperDimensions);
- DisableItem(testMenu, kGetAllPaperTypeInfo);
- }
-
- if (hasPages && !onLastPage)
- EnableItem(testMenu, kAheadPage);
- else
- DisableItem(testMenu, kAheadPage);
-
- if (hasPages && !onFirstPage)
- EnableItem(testMenu, kBackPage);
- else
- DisableItem(testMenu, kBackPage);
-
- if (!onLastPage && (myDocument->numPages > 1))
- EnableItem(testMenu, kApplyAboveFormat);
- else
- DisableItem(testMenu, kApplyAboveFormat);
- }
- }
-
-
- // This routine handles our menu command dispatching.
-
- void MyDoMenuCommand(long menuResult)
- {
- short menuID;
- short menuItem;
- long curPage;
- Str255 daName;
- OSErr err = noErr;
- WindowPtr aWindow;
- MyDocumentPtr aDocument;
-
- // Get the selected menu's ID, item and MenuHandle.
-
- menuID = menuResult >>16;
- menuItem = menuResult & 0xFFFF;
-
- switch (menuID)
- {
- case mApple:
- switch (menuItem)
- {
- case kAbout: // Display About box.
- MyDisplayAbout();
- break;
-
- default: // Handle DAs.
-
- GetItem(GetMHandle(mApple), menuItem, daName);
- OpenDeskAcc(daName);
- break;
- }
- break;
-
- case mFile:
- switch (menuItem)
- {
- case kOpen: // Open a document.
- err = MyNewDocument("\pUntitled", &myDocument);
- if (!err)
- {
- err = MyOpenDocument(&myDocument);
- // err = MyOpenDocument2(&myDocument);
- if (err)
- {
- Str255 pStr;
-
- MyCloseDocument(&myDocument);
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyOpenDocument!", err);
- MyDisplayInfo(pStr);
- }
- else
- ShowWindow(myDocument.documentWindow);
-
- }
- else
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyNewDocument!", err);
- MyDisplayInfo(pStr);
- }
- break;
-
- case kNew: // Create a new document.
- err = MyNewDocument("\pUntitled", &myDocument);
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyNewDocument!", err);
- MyDisplayInfo(pStr);
- }
- else
- ShowWindow(myDocument.documentWindow);
- break;
-
- case kClose: // Close a document.
- err = MyCloseDocument(&myDocument);
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyCloseDocument!", err);
- MyDisplayInfo(pStr);
- }
- break;
-
- case kSave: // Save a document to its original file.
- err = MySaveDocument(&myDocument, false);
- // err = MySaveDocument2(&myDocument, false);
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MySaveDocument!", err);
- MyDisplayInfo(pStr);
- }
- break;
-
- case kSaveAs: // Save a document to a new file.
- err = MySaveDocument(&myDocument, true);
- // err = MySaveDocument2(&myDocument, true);
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MySaveDocument!", err);
- MyDisplayInfo(pStr);
- }
- break;
-
- case kInsertPage: // Insert a page.
- err = MyInsertPage(&myDocument);
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyInsertPage!", err);
- MyDisplayInfo(pStr);
- }
- break;
-
- case kDeletePage: // Delete a page.
- err = MyDeletePage(&myDocument);
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyDeletePage!", err);
- MyDisplayInfo(pStr);
- }
- break;
-
- case kPageSetup: // Do a Page Setup.
-
- err = MyPageFormatDialog(&myDocument);
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyPageFormatDialog!", err);
- MyDisplayInfo(pStr);
- }
- break;
-
- case kDocSetup: // Do Document Setup.
- err = MyFormatDialog(&myDocument);
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyFormatDialog!", err);
- MyDisplayInfo(pStr);
- }
- break;
-
- case kPrintOne: // Print one.
- err = MyPrintOneCopy(&myDocument);
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyPrintOneCopy!", err);
- MyDisplayInfo(pStr);
- }
- break;
-
-
- case kPrint: // Print a document.
- err = MyPrintDialog(&myDocument);
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyPrintDialog!", err);
- MyDisplayInfo(pStr);
- }
- break;
-
- case kQuit: // Quit the application.
- gQuitting = true;
- while (aWindow = FrontWindow())
- {
- aDocument = (MyDocumentPtr) GetWRefCon(aWindow);
- MyCloseDocument(&myDocument);
- }
-
- break;
- }
- break;
-
- case mTest:
- switch (menuItem)
- {
- case kAheadPage: // Go ahead a page.
- MyAheadPage(FrontWindow());
- break;
-
- case kBackPage: // Go back a page.
- MyBackPage(FrontWindow());
- break;
-
- case kApplyAboveFormat: // Apply format from page above this one (wrap to page 1).
- curPage = myDocument.curPage;
-
- if (curPage == myDocument.numPages)
- curPage = 0;
-
- err = MyApplyPageFormat(&myDocument, myDocument.pageFormat[curPage]);
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyApplyPageFormat!", err);
- MyDisplayInfo(pStr);
- }
- break;
-
- case kAddForm: // Add form to format.
- err = MyAddFormatForm(&myDocument);
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyAddFormatForm!", err);
- MyDisplayInfo(pStr);
- }
- break;
-
- case kRemoveForm: // Remove form from format.
- err = MyRemoveFormatForm(&myDocument);
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyRemoveFormatForm!", err);
- MyDisplayInfo(pStr);
- }
- break;
-
- case kGetCopiesInfo: // Get the number of copies stored in a job.
- {
- short numCopies;
-
- err = MyGetJobCopies(&myDocument, &numCopies);
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyGetJobCopies!", err);
- MyDisplayInfo(pStr);
- }
- else
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s %i %s",
- "This job will print",
- numCopies, "copies.");
- MyDisplayInfo(pStr);
- }
- }
- break;
-
- case kGetFileNumPages: // Get the number of pages stored in a spool file.
- {
- long numPages;
- StandardFileReply sfReply;
- SFTypeList typeList;
-
- typeList[0] = kPrintFileType1;
- typeList[1] = kPrintFileType2;
- typeList[2] = kPrintFileType3;
- typeList[3] = kPrintFileType4;
-
- StandardGetFile(nil, 4, typeList, &sfReply);
-
- if (!sfReply.sfGood) break;
-
- err = MyGetPrintFilePages(&sfReply.sfFile, &numPages);
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyGetPrintFilePages!", err);
- MyDisplayInfo(pStr);
- }
- else
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s %i %s",
- "This file contains",
- numPages, "pages.");
- MyDisplayInfo(pStr);
- }
- }
- break;
-
- case kShowJobPrinterInfo: // Show the destination printer name, etc.
- err = MyShowJobPrinterInfo(&myDocument);
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyShowJobPrinterInfo!", err);
- MyDisplayInfo(pStr);
- }
- break;
-
- case kJobRefConTest: // Perform our Set/GXGetJobRefCon test.
- err = MyJobRefConTest(&myDocument);
-
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyJobRefConTest!", err);
- MyDisplayInfo(pStr);
- }
- break;
-
- case kReadFilePage: // Replace the current page with page 1 from a print file.
- {
- StandardFileReply sfReply;
- SFTypeList typeList;
- gxShape pgShape;
- gxFormat pgFormat;
-
- typeList[0] = kPrintFileType1;
- typeList[1] = kPrintFileType2;
- typeList[2] = kPrintFileType3;
- typeList[3] = kPrintFileType4;
-
- StandardGetFile(nil, 4, typeList, &sfReply);
-
- if (!sfReply.sfGood) break;
-
- err = MyReadPrintFilePage(&myDocument, &sfReply.sfFile, 1, &pgFormat, &pgShape);
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyReadPrintFilePage!", err);
- MyDisplayInfo(pStr);
- }
- else
- {
- if (myDocument.numPages != 0)
- {
- if (myDocument.pageFormat[myDocument.curPage -1] != nil)
- GXDisposeFormat(myDocument.pageFormat[myDocument.curPage -1]);
-
- GXDisposeShape(myDocument.documentPage[myDocument.curPage -1]);
- }
-
- myDocument.pageFormat[myDocument.curPage -1] = pgFormat;
- myDocument.documentPage[myDocument.curPage -1] = pgShape;
- if (myDocument.numPages == 0)
- {
- myDocument.curPage =
- myDocument.numPages = 1;
- }
-
- InvalRect(&(myDocument.documentWindow)->portRect);
- }
- }
- break;
-
- case kGetPaperTypeName: // Gets the current page's paper type.
- {
- Str255 pStr;
-
- err = MyGetPaperTypeName(&myDocument, pStr);
- if (err)
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyGetPaperTypeName!", err);
-
- MyDisplayInfo(pStr);
- break;
- }
-
- case kGetPaperDimensions: // Gets the current page's paper type dimensions.
- {
- gxRectangle pageBounds, paperBounds;
- Str255 pStr;
-
- err = MyGetPaperTypeDims(&myDocument, &pageBounds, &paperBounds);
-
- if (err)
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyGetPaperTypeDims!", err);
- else
- pStr[0] = sprintf(&pStr[1], "%s %i, %i, %i, %i. %s %i, %i, %i, %i.",
- "pageBounds =",
- pageBounds.top >>16,
- pageBounds.left >>16,
- pageBounds.bottom >>16,
- pageBounds.right >>16,
- "paperBounds =",
- paperBounds.top >>16,
- paperBounds.left >>16,
- paperBounds.bottom >>16,
- paperBounds.right >>16);
-
- MyDisplayInfo(pStr);
- break;
- }
-
- case kGetAllPaperTypeInfo: // Gets all names and dimensions of a job's paperType.
- err = MyListAllPaperTypes(&myDocument);
-
- if (err)
- {
- Str255 pStr;
-
- pStr[0] = sprintf(&pStr[1], "%s --> %i", "Error in MyListAllPaperTypes!", err);
- MyDisplayInfo(pStr);
- }
- break;
-
- case kShowPrinterResolution:
- MyShowJobPrinterResolution(&myDocument);
- break;
-
- }
- break;
- }
-
- HiliteMenu(0);
- }
-
-
- // MyWindowUpdate updates one of our windows.
-
- void MyWindowUpdate(WindowPtr whichWindow)
- {
- MyDocumentPtr myDocument;
- GrafPtr oldPort;
-
- if (((WindowPeek) whichWindow)->windowKind != userKind) return;
-
- GetPort(&oldPort);
- SetPort(whichWindow);
-
- BeginUpdate(whichWindow);
-
- myDocument = (MyDocumentPtr) GetWRefCon(whichWindow);
- EraseRect(&whichWindow->portRect);
-
- if (myDocument->numPages > 0)
- GXDrawShape(myDocument->documentPage[myDocument->curPage -1]);
-
- EndUpdate(whichWindow);
- SetPort(oldPort);
- }
-
-
- // This routine handles enabling and disabling menu items
- // when we're putting up, or tearing down print dialogs.
-
- void MyAdjustMenusForPrintDialogs(Boolean dialogGoingUp)
- {
- MenuHandle fileMenu, editMenu, testMenu;
-
- editMenu = GetMHandle(mEdit);
- fileMenu = GetMHandle(mFile);
- testMenu = GetMHandle(mTest);
-
- if (dialogGoingUp)
- {
- DisableItem(fileMenu, 0);
- DisableItem(testMenu, 0);
-
- HiliteMenu(0);
- DrawMenuBar();
- }
- else
- {
- DisableItem(editMenu, 0);
- EnableItem(fileMenu, 0);
- EnableItem(testMenu, 0);
- DrawMenuBar();
- }
-
- gInPrintDialog = dialogGoingUp;
- }
-
-
- // Override for GXPrintingEvent. It allows us to update our windows
- // when the moveable modal printing dialogs are moved.
-
- OSErr MyPrintingEventOverride(EventRecord *anEvent, Boolean filterEvent)
- {
- OSErr err = noErr;
-
- /* Handle events in whatever way is appropriate. MyDoEvent is our
- generic event handler. We don't pass it events that it shouldn't
- handle while print dialogs are displayed. */
-
- if (!filterEvent)
- switch (anEvent->what)
- {
- case mouseDown:
- case keyDown:
- case autoKey:
- break;
-
- default:
- err = MyDoEvent(anEvent);
- }
-
- return err;
- }
-
-
- // Change a document's format by using the job format dialog.
-
- OSErr MyFormatDialog(MyDocumentPtr myDocument)
- {
- OSErr err;
- gxDialogResult result;
- gxEditMenuRecord editMenuRec;
-
- // Fill in the location of the application’s Edit menu items and enable
- // the appropriate menu items.
-
- editMenuRec.editMenuID = mEdit;
- editMenuRec.cutItem = kCut;
- editMenuRec.copyItem = kCopy;
- editMenuRec.pasteItem = kPaste;
- editMenuRec.clearItem = kClear;
- editMenuRec.undoItem = kUndo;
-
- MyAdjustMenusForPrintDialogs(true);
-
- // Display the Document Setup dialog box.
-
- result = GXJobDefaultFormatDialog(myDocument->documentJob, &editMenuRec);
- err = GXGetJobError(myDocument->documentJob);
-
- // If the user chooses "Format" and no errors occurred, we perform any
- // document formatting that we need to.
-
- if ((err == noErr) && (result == gxOKSelected))
- {
- /*
- Place your application-specific code here if you need
- to repaginate the document.
- .
- .
- .
- */
- }
-
- MyAdjustMenusForPrintDialogs(false);
-
- return err;
- }
-
-
- // Change the current page's format by using the Format dialog.
-
- OSErr MyPageFormatDialog(MyDocumentPtr myDocument)
- {
- OSErr err = noErr;
- gxDialogResult result;
- gxEditMenuRecord editMenuRec;
- gxFormat pageFormat;
- Boolean newPgFormat = false;
-
- // Fill in the location of the application’s Edit menu items and enable
- // the appropriate menu items.
-
- editMenuRec.editMenuID = mEdit;
- editMenuRec.cutItem = kCut;
- editMenuRec.copyItem = kCopy;
- editMenuRec.pasteItem = kPaste;
- editMenuRec.clearItem = kClear;
- editMenuRec.undoItem = kUndo;
-
- MyAdjustMenusForPrintDialogs(true);
-
- // If we have an existing page format, we'll modify that. Otherwise, we'll
- // need to create a new format and use that.
-
- if (myDocument->pageFormat[myDocument->curPage -1] != nil)
- pageFormat = myDocument->pageFormat[myDocument->curPage -1];
- else
- {
- pageFormat = GXNewFormat(myDocument->documentJob);
- newPgFormat = true;
- err = GXGetJobError(myDocument->documentJob);
- }
-
- // If no errors, display the format dialog.
-
- if (err == noErr)
- {
- result = GXFormatDialog(pageFormat, &editMenuRec, nil);
-
- switch (result)
- {
-
- // If the user selected "Revert", use the default job format with this page.
- // For our application, we indicate this by storing nil for the format
- // reference in our structure.
- //
- // If "OK" was selected, store the new format with this page.
-
- case gxRevertSelected:
- GXDisposeFormat(pageFormat);
- pageFormat = nil;
-
- case gxOKSelected:
- myDocument->pageFormat[myDocument->curPage -1] = pageFormat;
-
- /*
- Place code here if your application needs to
- adjust the document based on the new page format.
- .
- .
- .
-
- */
- break;
-
-
- // If the user selected "Cancel", dispose of our cloned copy of the default
- // job format, if we made one.
-
- case gxCancelSelected:
- if (newPgFormat) GXDisposeFormat(pageFormat);
- break;
- }
- }
-
- MyAdjustMenusForPrintDialogs(false);
-
- return err;
- }
-
-
- // Change the current page's format to the passed format.
-
- OSErr MyApplyPageFormat(MyDocumentPtr myDocument, gxFormat aNewFormat)
- {
- OSErr err = noErr;
- gxFormat pageFormat;
-
- // If the passed format is not the same as the job format (or nil), clone it so
- // it can be shared by different pages. If it is the job format (or nil), set
- // our reference to nil, which tells our application to use the job format for
- // this page.
-
- if ((aNewFormat != nil) && (aNewFormat != GXGetJobFormat(myDocument->documentJob, 1)))
- {
- pageFormat = GXCloneFormat(aNewFormat);
- err = GXGetJobError(myDocument->documentJob);
- }
- else
- pageFormat = nil;
-
-
- // If there are no errors, dispose of the old page format and store
- // the new one. Reformat the page, if need be.
-
- if (err == noErr)
- {
- if (myDocument->pageFormat[myDocument->curPage -1] != nil)
- GXDisposeFormat(myDocument->pageFormat[myDocument->curPage -1]);
-
- myDocument->pageFormat[myDocument->curPage -1] = pageFormat;
-
- /*
- Place code here if your application needs to
- adjust the document based on the new page format.
- .
- .
- .
-
- */
- }
-
- return err;
- }
-
-
- // This is our override for FormatDialog. We add a panel and forward the message
- // so that other handlers are called.
-
- OSErr MyFormatDialogOverride(gxFormat aFormat, StringPtr title, gxDialogResult *result)
- {
- OSErr err;
-
- err = MySetUpByPagePanel(aFormat, GXGetMessageHandlerResFile());
- if (!err) err = Forward_GXFormatDialog(aFormat, title, result);
-
- return err;
- }
-
-
- // This is the routine which adds our panel to the format dialog.
-
- OSErr MySetUpByPagePanel(gxFormat aFormat, short ourResFile)
- {
- OSErr err;
- Collection fmtCollection;
- gxPanelSetupRecord panelInfo;
- MyKindaCollectionRec mySettings;
-
- // We first get the format collection, and then look for one of our collection
- // items in it. This collection item is where our default settings will be stored.
-
- fmtCollection = GXGetFormatCollection(aFormat);
-
- err = GetCollectionItem(fmtCollection, kMyKindaCollectionType,
- kMyKindaCollectionTagID, nil, &mySettings);
-
- // If our collection item does not exist, create one and add it to the format
- // collection so that we have default settings for our dialog panel.
-
- if (err == collectionItemNotFoundErr)
- {
- mySettings.isTurnedOn = false;
- mySettings.dayOfWeek = 7;
-
- err = AddCollectionItem(fmtCollection, kMyKindaCollectionType,
- kMyKindaCollectionTagID, sizeof(MyKindaCollectionRec),
- &mySettings);
- }
-
- // Now, install our panel. We need to specify the type of panel it is, the resource ID
- // of our 'panl' resource, and in which resource file it's located. The refCon field is
- // for our own use, although we don't use it here.
-
- if (!err)
- {
- panelInfo.panelKind = gxApplicationPanel;
- panelInfo.panelResId = r_MyFormatPanelResID;
- panelInfo.resourceRefNum = ourResFile;
- panelInfo.refCon = 0;
-
- err = GXSetupDialogPanel(&panelInfo);
- }
-
- return err;
- }
-
-
- OSErr MyPrintDocument(MyDocumentPtr myDocument)
- {
- // return MyPrintDocument1(myDocument); // printpage w/o formats
- // return MyPrintDocument2(myDocument); // startpage/finishpage w/o formats
- return MyPrintDocument3(myDocument); // printpage & by-page formats
- // return MyPrintDocument4(myDocument); // printpage & poll after indiv. functions
- }
-
-
- // This routine prints the pages of a document using GXPrintPage. You would
- // use this function if your application stored the data for each page as
- // single shapes.
-
- OSErr MyPrintDocument1(MyDocumentPtr myDocument)
- {
- OSErr err;
- long firstPage, lastPage, numPages, pg;
-
- // Determine which pages the user selected to print. If the user specifies
- // a page range that is greater than the actual number of pages in the
- // document, only print those pages that are actually in the document.
-
- GXGetJobPageRange(myDocument->documentJob, &firstPage, &lastPage);
-
- if (lastPage > myDocument->numPages)
- lastPage = myDocument->numPages;
-
- // Calculate the total number of pages to print, and begin printing if there
- // are no errors.
-
- numPages = lastPage - firstPage +1;
- err = GXGetJobError(myDocument->documentJob);
-
- if (err == noErr)
- {
-
- // Start printing.
-
- GXStartJob(myDocument->documentJob, myDocument->documentTitle, numPages);
- err = GXGetJobError(myDocument->documentJob);
-
- // Loop through each page of the document, calling GXPrintPage for each page's
- // shape. In this example, we use the job's default format to print each page.
- // After sending each page, check for errors so that we can exit the loop
- // if any occur.
-
- if (err == noErr)
- {
- for (pg = firstPage; (err == noErr) && (pg <= lastPage); pg++)
- {
- GXPrintPage(myDocument->documentJob,
- pg,
- GXGetJobFormat(myDocument->documentJob, 1),
- myDocument->documentPage[pg -1]);
-
- err = GXGetJobError(myDocument->documentJob);
- }
-
- // Finish printing.
-
- GXFinishJob(myDocument->documentJob);
- err = GXGetJobError(myDocument->documentJob);
- }
- }
-
- return err;
- }
-
-
- // This routine prints the pages of a document using GXStartPage, GXDrawShape, and
- // GXFinishPage. You would normally use this function if your application stored
- // the data for each page as multiple shapes.
-
- OSErr MyPrintDocument2(MyDocumentPtr myDocument)
- {
- OSErr err;
- long firstPage, lastPage, numPages, pg;
-
- // Determine which pages the user selected to print. If the user specifies
- // a page range that is greater than the actual number of pages in the
- // document, only print those pages that are actually in the document.
-
- GXGetJobPageRange(myDocument->documentJob, &firstPage, &lastPage);
-
- if (lastPage > myDocument->numPages)
- lastPage = myDocument->numPages;
-
- // Calculate the total number of pages to print, and begin printing if there
- // are no errors.
-
- numPages = lastPage - firstPage +1;
- err = GXGetJobError(myDocument->documentJob);
-
- if (err == noErr)
- {
-
- // Start printing.
-
- GXStartJob(myDocument->documentJob, myDocument->documentTitle, numPages);
- err = GXGetJobError(myDocument->documentJob);
-
- // For each page we print, call GXStartPage, draw, and call GXFinishPage. In this
- // example, we use the job's default format, the document's viewPort, and draw
- // only a single shape for each page.
-
- if (err == noErr)
- {
- for (pg = firstPage; (err == noErr) && (pg <= lastPage); pg++)
- {
- // Start the page.
-
- GXStartPage(myDocument->documentJob,
- pg,
- GXGetJobFormat(myDocument->documentJob, 1),
- 1,
- &myDocument->documentViewPort);
-
- err = GXGetJobError(myDocument->documentJob);
-
- // If there were no errors, draw the data for the page.
-
- if (err == noErr)
- {
- GXDrawShape(myDocument->documentPage[pg -1]);
- err = (OSErr) GXGetGraphicsError(nil);
- }
-
- // Finish the page, even if there were errors.
-
- GXFinishPage(myDocument->documentJob);
- }
-
- // Finish printing.
-
- GXFinishJob(myDocument->documentJob);
- err = GXGetJobError(myDocument->documentJob);
- }
- }
-
- return err;
- }
-
-
- // This routine prints the pages of a document using GXPrintPage. It also
- // prints using the stored page formats for this document. You would use
- // this function if your application stored the data for each page as
- // single shapes.
-
- OSErr MyPrintDocument3(MyDocumentPtr myDocument)
- {
- OSErr err;
- long firstPage, lastPage, numPages, pg;
- gxFormat pgFormat;
-
- // Determine which pages the user selected to print. If the user specifies
- // a page range that is greater than the actual number of pages in the
- // document, only print those pages that are actually in the document.
-
- GXGetJobPageRange(myDocument->documentJob, &firstPage, &lastPage);
-
- if (lastPage > myDocument->numPages)
- lastPage = myDocument->numPages;
-
- // Calculate the total number of pages to print, and begin printing if there
- // are no errors.
-
- numPages = lastPage - firstPage +1;
- err = GXGetJobError(myDocument->documentJob);
-
- if (err == noErr)
- {
-
- // Start printing.
-
- GXStartJob(myDocument->documentJob, myDocument->documentTitle, numPages);
- err = GXGetJobError(myDocument->documentJob);
-
-
- // Loop through each page of the document, calling GXPrintPage for each page's
- // shape. In this example, we use the job's default format to print each
- // page. After sending each page, check for errors so that we can exit the
- // loop if any occur.
-
- if (err == noErr)
- {
- for (pg = firstPage; (err == noErr) && (pg <= lastPage); pg++)
- {
- pgFormat = myDocument->pageFormat[pg -1];
-
- if (pgFormat == nil)
- pgFormat = GXGetJobFormat(myDocument->documentJob, 1);
-
- GXPrintPage(myDocument->documentJob,
- pg,
- pgFormat,
- myDocument->documentPage[pg -1]);
-
- err = GXGetJobError(myDocument->documentJob);
- }
-
- // Finish printing.
-
- GXFinishJob(myDocument->documentJob);
- err = GXGetJobError(myDocument->documentJob);
- }
- }
-
- return err;
- }
-
-
- // This routine prints the pages of a document using GXPrintPage. You would
- // use this function if your application stored the data for each page as
- // single shapes.
-
- OSErr MyPrintDocument4(MyDocumentPtr myDocument)
- {
- OSErr err;
- long firstPage, lastPage, numPages, pg;
-
- // Determine which pages the user selected to print. If the user specifies
- // a page range that is greater than the actual number of pages in the
- // document, only print those pages that are actually in the document.
-
- GXGetJobPageRange(myDocument->documentJob, &firstPage, &lastPage);
- err = GXGetJobError(myDocument->documentJob);
-
- if (err == noErr)
- {
- if (lastPage > myDocument->numPages)
- lastPage = myDocument->numPages;
-
- // Calculate the total number of pages to print, and begin printing if there
- // are no errors.
-
- numPages = lastPage - firstPage + 1;
-
- GXStartJob(myDocument->documentJob, myDocument->documentTitle, numPages);
- err = GXGetJobError(myDocument->documentJob);
-
- // Loop through each page of the document, calling GXPrintPage for each page's
- // shape.
-
- if (err == noErr)
- {
- for (pg = firstPage; (err == noErr) && (pg <= lastPage); pg++)
- {
- GXPrintPage(myDocument->documentJob,
- pg,
- GXGetJobFormat(myDocument->documentJob, 1),
- myDocument->documentPage[pg -1]);
-
- err = GXGetJobError(myDocument->documentJob);
- }
-
- // Finish printing.
-
- GXFinishJob(myDocument->documentJob);
- err = GXGetJobError(myDocument->documentJob);
- }
- }
-
- return err;
- }
-
-
- // This routine sets up our job's collection items
- // to correctly print one full copy of the document,
- // and then it initiates printing.
-
- OSErr MyPrintOneCopy(MyDocumentPtr whichDocument)
- {
- OSErr err;
- Collection jobCollection;
- gxCopiesInfo copiesInfo;
- gxFileDestinationInfo destInfo;
- gxPageRangeInfo pageRangeInfo;
- Ptr oldCopiesInfo = nil, oldPageRangeInfo = nil, oldDestInfo = nil;
- long oldCopiesSize, oldPageRangeInfoSize, oldDestInfoSize;
-
-
- /* Get the job collection and set it up to print one copy… */
-
- jobCollection = GXGetJobCollection(whichDocument->documentJob);
-
-
- /* Set number of copies to 1. */
-
- copiesInfo.copies = 1;
- err = MyReplaceCollectionItem(&copiesInfo, sizeof(gxCopiesInfo),
- gxCopiesTag, gxPrintingTagID,
- jobCollection, &oldCopiesInfo, &oldCopiesSize);
- nrequire(err, ReplaceCopies_error);
-
-
- /* Set page range to "all". */
-
- pageRangeInfo.simpleRange.optionChosen = gxDefaultPageRange;
- pageRangeInfo.minFromPage = 1;
- pageRangeInfo.simpleRange.fromPage = 1;
- pageRangeInfo.maxToPage = whichDocument->numPages;
- pageRangeInfo.simpleRange.toPage = whichDocument->numPages;
- pageRangeInfo.simpleRange.printAll = true;
- err = MyReplaceCollectionItem(&pageRangeInfo, sizeof(gxPageRangeInfo),
- gxPageRangeTag, gxPrintingTagID,
- jobCollection, &oldPageRangeInfo, &oldPageRangeInfoSize);
- nrequire(err, ReplacePageRange_error);
-
-
- /* Set destination to "printer". */
-
- destInfo.toFile = false;
- err = MyReplaceCollectionItem(&destInfo, sizeof(gxFileDestinationInfo),
- gxFileDestinationTag, gxPrintingTagID,
- jobCollection, &oldDestInfo, &oldDestInfoSize);
- nrequire(err, ReplaceDestination_error);
-
-
- /* Print one copy of our document. */
-
- err = MyPrintDocument(whichDocument);
-
-
- /* Restore original number of copies, page range, and output
- destination in case anybody uses that info. */
-
- ReplaceCopies_error:
- MyReplaceCollectionItem(oldCopiesInfo, oldCopiesSize,
- gxCopiesTag, gxPrintingTagID,
- jobCollection, nil, nil);
-
- ReplacePageRange_error:
- MyReplaceCollectionItem(oldPageRangeInfo, oldPageRangeInfoSize,
- gxPageRangeTag, gxPrintingTagID,
- jobCollection, nil, nil);
-
- ReplaceDestination_error:
- MyReplaceCollectionItem(oldDestInfo, oldDestInfoSize,
- gxFileDestinationTag, gxPrintingTagID,
- jobCollection, nil, nil);
-
-
- /* Dispose of the pointers that MyReplaceCollectionItem created. */
-
- if (oldCopiesInfo)
- DisposePtr(oldCopiesInfo);
-
- if (oldPageRangeInfo)
- DisposePtr(oldPageRangeInfo);
-
- if (oldDestInfo)
- DisposePtr(oldDestInfo);
-
- return err;
- }
-
-
- // MyReplaceCollectionItem is a generic routine that replaces a
- // collection item with the passed data. If the oldData pointer
- // is not nil, the data that's being replaced is returned in it.
- // (If the item doesn't already exist, then a copy of the newData
- // is returned instead.)
-
- OSErr MyReplaceCollectionItem(void *newData, long collectSize,
- OSType collectType, long collectID,
- Collection whichCollection,
- Ptr *oldData, long *oldDataSize)
- {
- OSErr err = noErr;
- long index;
-
- /*
- If we're supposed to return the old data, get it.
- If there is no old data, return a copy of the new data.
- */
-
- if (oldData)
- {
- err = GetCollectionItemInfo(whichCollection,
- collectType,
- collectID,
- dontWantIndex,
- oldDataSize,
- dontWantAttributes);
-
- if (err)
- {
- *oldDataSize = collectSize;
- *oldData = NewPtrSys(*oldDataSize);
- if (!(err = MemError()))
- BlockMove(newData, *oldData, collectSize);
- }
- else
- {
- *oldData = NewPtrSys(*oldDataSize);
- if (!(err = MemError()))
- err = GetCollectionItem(whichCollection,
- collectType,
- collectID,
- dontWantSize,
- *oldData);
- }
- }
-
- nrequire(err, CouldNotSetOldData);
-
-
- // If we're adding a new collection item, do so. Otherwise, get the
- // existing item's index and replace the old collection item.
-
- err = AddCollectionItem(whichCollection,
- collectType,
- collectID,
- collectSize,
- newData);
-
- if (err == collectionItemLockedErr)
- {
- err = GetCollectionItemInfo(whichCollection,
- collectType,
- collectID,
- &index,
- dontWantSize,
- dontWantAttributes);
- if (!err)
- err = ReplaceIndexedCollectionItem(whichCollection,
- index,
- collectSize,
- newData);
- }
-
- CouldNotSetOldData:
- return err;
- }
-
-
- gxColorProfile MyGetFormattingPrinterProfile(MyDocumentPtr myDocument, gxColorSpace *theSpace)
- {
- gxShape deviceBitMap;
- gxBitmap deviceBits;
- gxPrinter formattingPrinter;
- gxColorProfile theProfile;
- gxViewDevice printerDevice;
-
- /* Get the first profile for the formatting printer. */
-
- formattingPrinter = GXGetJobFormattingPrinter(myDocument->documentJob);
- GXFindPrinterProfile(formattingPrinter, nil, 1, &theProfile);
-
- /*
- Now look at the characteristics of the formatting printer's
- viewdevice and retrieve its color space.
- */
- printerDevice = GXGetPrinterViewDevice(formattingPrinter, 0);
- deviceBitMap = GXGetViewDeviceBitmap(printerDevice);
- GXGetBitmap(deviceBitMap, &deviceBits, nil);
- *theSpace = deviceBits.space;
- GXDisposeShape(deviceBitMap);
-
- return theProfile;
- }
-
-
- Boolean MyMakePrinterColor(MyDocumentPtr myDocument, gxColor *sourceColor, gxColor *printedColor)
- {
- gxColorProfile printerProfile;
- gxColorSpace printerSpace;
- Boolean inGamut;
-
- printerProfile = MyGetFormattingPrinterProfile(myDocument, &printerSpace);
-
- /*
- Copy the source color, see if it's in gamut, and convert it
- into the device's color space.
- */
-
- *printedColor = *sourceColor;
- inGamut = GXCheckColor(printedColor, printerSpace, nil, printerProfile);
- GXConvertColor(printedColor, printerSpace, nil, printerProfile);
-
- return inGamut;
- }
-
-
- OSErr MyPrintDialog(MyDocumentPtr myDocument)
- {
- OSErr err = noErr;
- gxDialogResult result;
- gxEditMenuRecord editMenuRec;
-
- /*
- Fill in the location of the application’s Edit menu
- items and enable the appropriate menu items.
- */
- editMenuRec.editMenuID = mEdit;
- editMenuRec.cutItem = kCut;
- editMenuRec.copyItem = kCopy;
- editMenuRec.pasteItem = kPaste;
- editMenuRec.clearItem = kClear;
- editMenuRec.undoItem = kUndo;
-
- MyAdjustMenusForPrintDialogs(true);
-
- /*
- Uncommenting any one of these lines will alter the appearance
- of the page range fields in the General Print panel. However,
- this only works correctly for f2c1.2 or later!!!!
-
- You must also uncomment both GXInstallApplicationOverride calls
- below.
- */
-
- // err = MyConfigurePageRange1(myDocument);
- // err = MyConfigurePageRange2(myDocument);
- // err = MyConfigurePageRange3(myDocument);
- nrequire(err, CouldNotConfigurePageRange);
-
- // GXInstallApplicationOverride(myDocument->documentJob, gxParsePageRange, NewGXParsePageRangeProc(MyParsePageRangeOverride));
-
- /* Display the Print dialog box. */
-
- result = GXJobPrintDialog(myDocument->documentJob, &editMenuRec);
- err = GXGetJobError(myDocument->documentJob);
-
- // GXInstallApplicationOverride(myDocument->documentJob, gxParsePageRange, NewGXParsePageRangeProc(nil));
-
-
- /*
- If we didn't receive any errors and the user selected the
- “OK” button, call our printing routine to output the pages.
- */
- if ((err == noErr) && (result == gxOKSelected))
- err = MyPrintDocument(myDocument);
-
- CouldNotConfigurePageRange:
- MyAdjustMenusForPrintDialogs(false);
-
- return err;
- }
-
-
- /*
- In this routine, we're supposed to check the validity of the "From page"
- and "To page" strings. If both are good, return gxRangeParsed.
- Otherwise, return gxRangeBadFromValue or gxRangeBadToValue. Being a
- cheesy sample, we always return gxRangeParsed.
- */
-
- gxParsePageRangeResult MyPageRangeValidityCheck(StringPtr fromString, StringPtr toString)
- {
- #pragma unused(fromString, toString)
-
- return gxRangeParsed;
- }
-
-
- // This is an override for gxParsePageRange. In here,
- // we verify that the user's page range is valid.
-
- OSErr MyParsePageRangeOverride(StringPtr fromString, StringPtr toString, gxParsePageRangeResult *result)
- {
-
- /*
- Determine if the "To page" and "From page" strings are
- valid. If not, our MyPageRangeValidityCheck routine
- will return gxRangeBadFromValue or gxRangeBadToValue.
- Otherwise it will return gxRangeParsed.
- */
- if (*result == gxRangeNotParsed)
- *result = MyPageRangeValidityCheck(fromString, toString);
-
- return noErr;
- }
-
-
- // This routine sets up the page range collection item to
- // use the default page range style (numeric).
-
- OSErr MyConfigurePageRange1(MyDocumentPtr myDocument)
- {
- OSErr err;
- gxPageRangeInfo **pageRangeHdl;
-
- /*
- Create a handle to store the page range collection itme in,
- and then retrieve it.
- */
- pageRangeHdl = (gxPageRangeInfo **) NewHandleClear(sizeof(gxPageRangeInfo));
- nrequire_action(err, NewHandleClear_Failed, err = MemError(););
-
- err = GetCollectionItemHdl(GXGetJobCollection(myDocument->documentJob),
- gxPageRangeTag,
- gxPrintingTagID,
- (Handle) pageRangeHdl);
-
- nrequire(err, GetCollectionItemHdl_Failed);
-
- /*
- Indicate that we're using the default page range format, and that
- we don't want the "all pages" radio button selected. We also
- indicate that we're printing pages 1 through 4.
- */
- (*pageRangeHdl)->simpleRange.optionChosen = gxDefaultPageRange;
- (*pageRangeHdl)->simpleRange.printAll = false;
-
- (*pageRangeHdl)->simpleRange.fromPage = 1;
- (*pageRangeHdl)->simpleRange.toPage = 4;
- (*pageRangeHdl)->minFromPage = 1;
- (*pageRangeHdl)->maxToPage = 9999;
-
- /* Add (or replace) the collection item, and dispose of its handle. */
-
- err = AddCollectionItemHdl(GXGetJobCollection(myDocument->documentJob),
- gxPageRangeTag,
- gxPrintingTagID,
- (Handle) pageRangeHdl);
-
- GetCollectionItemHdl_Failed:
- DisposHandle((Handle) pageRangeHdl);
-
- NewHandleClear_Failed:
- return err;
- }
-
-
- // This routine sets up the page range collection item to
- // use the replace page range style, which replaces the
- // "From-To" editText fields with one editText field.
-
- OSErr MyConfigurePageRange2(MyDocumentPtr myDocument)
- {
- OSErr err;
- gxPageRangeInfo **pageRangeHdl;
- Str31 FromToTitle = "\pChapter 5";
- long titleSize = FromToTitle[0] +1;
-
- /*
- Create a handle to store the page range collection itme in,
- and then retrieve it.
- */
- pageRangeHdl = (gxPageRangeInfo **) NewHandleClear(sizeof(gxPageRangeInfo));
- nrequire_action(err, NewHandleClear_Failed, err = MemError(););
-
- err = GetCollectionItemHdl(GXGetJobCollection(myDocument->documentJob),
- gxPageRangeTag,
- gxPrintingTagID,
- (Handle) pageRangeHdl);
-
- nrequire(err, GetCollectionItemHdl_Failed);
-
- /*
- Indicate that we're replacing the "From-To" dialog items with
- one editText field, and that we don't want the "all pages"
- radio button selected. We also indicate that we want the
- second radio button's editText field to be set to our title,
- "Chapter 5".
- */
- (*pageRangeHdl)->simpleRange.optionChosen = gxReplacePageRange;
- (*pageRangeHdl)->simpleRange.printAll = false;
-
- SetHandleSize((Handle) pageRangeHdl, sizeof(gxPageRangeInfo) +titleSize -1);
- nrequire_action(err, SetHandleSize_Failed, err = MemError(););
-
- BlockMove(FromToTitle, (*pageRangeHdl)->replaceString, titleSize);
-
- /* Add (or replace) the collection item, and dispose of its handle. */
-
- err = AddCollectionItemHdl(GXGetJobCollection(myDocument->documentJob),
- gxPageRangeTag,
- gxPrintingTagID,
- (Handle) pageRangeHdl);
-
- SetHandleSize_Failed:
- GetCollectionItemHdl_Failed:
- DisposHandle((Handle) pageRangeHdl);
-
- NewHandleClear_Failed:
- return err;
- }
-
-
- // This routine sets up the page range collection item to
- // use the custom page range style, which uses the
- // "From-To" editText fields but allows non-standard
- // page numbering.
-
- OSErr MyConfigurePageRange3(MyDocumentPtr myDocument)
- {
- OSErr err;
- gxPageRangeInfo **pageRangeHdl;
-
- /*
- Create a handle to store the page range collection itme in,
- and then retrieve it.
- */
- pageRangeHdl = (gxPageRangeInfo **) NewHandleClear(sizeof(gxPageRangeInfo));
- nrequire_action(err, NewHandleClear_Failed, err = MemError(););
-
- err = GetCollectionItemHdl(GXGetJobCollection(myDocument->documentJob),
- gxPageRangeTag,
- gxPrintingTagID,
- (Handle) pageRangeHdl);
-
- nrequire(err, GetCollectionItemHdl_Failed);
-
- /*
- Indicate that we're using the standard "From-To" editText fields,
- but are using a custom format for our page range values. Specify
- that we don't want the "all pages" radio button selected and that
- we want the "From" field to contain "iii" and the "To" field to
- contain "VI".
- */
- (*pageRangeHdl)->simpleRange.optionChosen = gxCustomizePageRange;
- (*pageRangeHdl)->simpleRange.printAll = false;
-
- BlockMove("iii", &(*pageRangeHdl)->fromString[1], 3);
- (*pageRangeHdl)->fromString[0] = 3;
- BlockMove("VI", &(*pageRangeHdl)->toString[1], 2);
- (*pageRangeHdl)->toString[0] = 2;
-
- /* Add (or replace) the collection item, and dispose of its handle. */
-
- err = AddCollectionItemHdl(GXGetJobCollection(myDocument->documentJob),
- gxPageRangeTag,
- gxPrintingTagID,
- (Handle) pageRangeHdl);
-
- GetCollectionItemHdl_Failed:
- DisposHandle((Handle) pageRangeHdl);
-
- NewHandleClear_Failed:
- return err;
- }
-
-
- // Create a new document. docName is a Pascal string containing the
- // name of the document, myDocument is a pointer to one of our
- // MyDocumentRec structures.
-
- OSErr MyNewDocument(Str31 docName, MyDocumentPtr myDocument)
- {
- OSErr err;
- Rect bounds;
-
- myDocument->numPages = 0; // There are no pages yet.
- myDocument->curPage = 0;
- myDocument->documentFSSpec.name[0] = 0; // Indicates a new document, not one
- // which has been loaded.
-
- // Create a new job for our document and install our overrides for
- // PrintingEvent and FormatDialog.
-
- err = GXNewJob(&myDocument->documentJob);
-
- if (err == noErr)
- {
-
- // Now install our application override for PrintingEvent so that we can
- // support the new movable-modal printing dialog boxes.
-
- GXInstallApplicationOverride(myDocument->documentJob, gxPrintingEvent,
- NewGXPrintingEventProc(MyPrintingEventOverride));
- GXInstallApplicationOverride(myDocument->documentJob, gxFormatDialog,
- NewGXFormatDialogProc(MyFormatDialogOverride));
-
-
- // Store the document name. We limit our document names to 31 characters
- // (plus a length byte).
-
- if (docName[0] > 31)
- docName[0] = 31;
-
- BlockMove(&docName[0], &myDocument->documentTitle[0], (long) docName[0] +1);
-
- /*
- Additional application-specific document initialization can go here.
-
- .
- .
- .
-
- Below, we create a window and a viewport for the document. We store
- the pointer to our MyDocumentRec structure in the window's refCon field.
-
- */
-
- SetRect(&bounds, 30, 60, 400, 500);
- myDocument->documentWindow = NewWindow(nil, &bounds, docName, false, noGrowDocProc,
- (WindowPtr) -1, true, (long) myDocument);
- err = MemError();
-
- if (err == noErr)
- {
- SetPort(myDocument->documentWindow);
- myDocument->documentViewPort = GXNewWindowViewPort(myDocument->documentWindow);
- err = GXGetGraphicsError(nil);
-
- if (err != noErr) DisposeWindow(myDocument->documentWindow);
- }
-
- if (err != noErr) GXDisposeJob(myDocument->documentJob);
- }
-
- return err;
- }
-
-
- // Close the document passed and free up any memory we allocated for it.
-
- OSErr MyCloseDocument(MyDocumentPtr myDocument)
- {
- OSErr err = noErr, jobErr;
- long pg;
-
- // For each page in the document, dispose of the page's shape.
-
- for (pg = 1; pg <= myDocument->numPages; pg++)
- GXDisposeShape(myDocument->documentPage[pg -1]);
-
-
- // Dispose of the the document's job (and job formats).
-
- jobErr = GXDisposeJob(myDocument->documentJob);
- if (err == noErr) err = jobErr;
-
- /*
- Place any application-specific code to close a document here.
-
- .
- .
- .
-
- Below, we dispose of the document's viewPort and window.
-
- */
-
- GXDisposeViewPort(myDocument->documentViewPort);
- DisposeWindow(myDocument->documentWindow);
-
- return err;
- }
-
-
- // This routine saves a document and its corresponding job to disk. It
- // also saves a format collection item containing our page<->format
- // relationships.
-
- OSErr MySaveDocument(MyDocumentPtr myDocument, Boolean doingSaveAs)
- {
- OSErr err;
- Handle theJobData, oldJobData;
- short dataRefNum = -1;
- short oldResFile, resRefNum = -1;
- FSSpec *docFSSpec;
- StandardFileReply sfReply;
- FInfo docFInfo;
-
- // Create a handle to store the job in, then flatten the job into our handle.
-
- oldResFile = CurResFile();
- theJobData = NewHandle(0);
- err = MemError();
-
- if (err == noErr)
- {
-
- // Store the document's page-to-format correspondences, then flatten the job.
-
- err = MySaveFormatRefs(myDocument);
-
- if (err == noErr)
- {
- GXFlattenJobToHdl(myDocument->documentJob, theJobData);
- err = GXGetJobError(myDocument->documentJob);
- }
-
- if (err == noErr)
- {
- docFSSpec = &myDocument->documentFSSpec;
-
- // If we're doing a "Save as…", display the StandardFile dialog and have the user
- // select a place to save the file.
-
- if (doingSaveAs)
- {
- StandardPutFile("\pSave document:", myDocument->documentTitle, &sfReply);
-
- if (!sfReply.sfGood)
- return noErr;
-
- // If we're replacing an existing file, delete it. Create our new file and set its
- // creator and type.
-
- if (sfReply.sfReplacing)
- err = HDelete(sfReply.sfFile.vRefNum, sfReply.sfFile.parID, sfReply.sfFile.name);
-
- if (err == noErr)
- {
- HCreateResFile(sfReply.sfFile.vRefNum, sfReply.sfFile.parID, sfReply.sfFile.name);
- HGetFInfo(sfReply.sfFile.vRefNum, sfReply.sfFile.parID,
- sfReply.sfFile.name, &docFInfo);
-
- docFInfo.fdCreator = kMyDocCreator;
- docFInfo.fdType = kMyDocType;
-
- err = HSetFInfo(sfReply.sfFile.vRefNum, sfReply.sfFile.parID,
- sfReply.sfFile.name, &docFInfo);
- }
-
- // If we're successful in creating the file, set our document's FSSpec info, its
- // title and its window's title.
-
- if (err == noErr)
- err = ResError();
-
- if (err) return err;
-
- BlockMove(&sfReply.sfFile, docFSSpec, sizeof(FSSpec));
- BlockMove(&sfReply.sfFile.name, myDocument->documentTitle,
- (long) sfReply.sfFile.name[0] +1);
-
- SetWTitle(myDocument->documentWindow, myDocument->documentTitle);
- }
-
- // Open the file's data fork and resource fork.
-
- err = FSpOpenDF(docFSSpec, fsRdWrPerm, &dataRefNum);
-
- if (err == noErr)
- {
- resRefNum = HOpenResFile(docFSSpec->vRefNum, docFSSpec->parID,
- docFSSpec->name, fsRdWrPerm);
- err = ResError();
- }
-
- // If there's an existing job resource, delete it.
-
- if (err == noErr)
- {
- UseResFile(resRefNum);
- oldJobData = Get1Resource(kMyJobType, kMyJobID);
- if (oldJobData != nil)
- {
- RmveResource(oldJobData);
- UpdateResFile(resRefNum);
- DisposHandle(oldJobData);
- }
-
- // Add our new job resource.
-
- AddResource(theJobData, kMyJobType, kMyJobID, "\p");
- err = ResError();
-
- if (err == noErr)
- {
- WriteResource(theJobData);
- UpdateResFile(resRefNum);
- ReleaseResource(theJobData);
- }
-
-
- // Now write out the data for our document's pages.
-
- /*
- Place your application-specific code here to save
- other data associated with the document.
- .
- .
- .
- */
- }
-
- // Close the data and resource forks of this document.
-
- if (dataRefNum != -1) FSClose(dataRefNum);
- if (resRefNum != -1) CloseResFile(resRefNum);
- }
- else
- DisposHandle(theJobData);
- }
-
- UseResFile(oldResFile);
- return err;
- }
-
-
- // This routine saves a document and its corresponding job to disk.
- // It saves the job in the data fork of the document.
-
- OSErr MySaveDocument2(MyDocumentPtr myDocument, Boolean doingSaveAs)
- {
- OSErr err;
- short dataRefNum = -1;
- short oldResFile, resRefNum = -1;
- FSSpec *docFSSpec;
- StandardFileReply sfReply;
- FInfo docFInfo;
-
- // Create a handle to store the job in, then flatten the job into our handle.
-
- oldResFile = CurResFile();
- err = MemError();
-
- if (err == noErr)
- {
- docFSSpec = &myDocument->documentFSSpec;
-
- // If we're doing a "Save as…", display the StandardFile dialog and have the user
- // select a place to save the file.
-
- if (doingSaveAs)
- {
- StandardPutFile("\pSave document:", myDocument->documentTitle, &sfReply);
-
- if (!sfReply.sfGood)
- return noErr;
-
- // If we're replacing an existing file, delete it. Create our new file and set its
- // creator and type.
-
- if (sfReply.sfReplacing)
- err = HDelete(sfReply.sfFile.vRefNum, sfReply.sfFile.parID, sfReply.sfFile.name);
-
- if (err == noErr)
- {
- HCreateResFile(sfReply.sfFile.vRefNum, sfReply.sfFile.parID, sfReply.sfFile.name);
- HGetFInfo(sfReply.sfFile.vRefNum, sfReply.sfFile.parID,
- sfReply.sfFile.name, &docFInfo);
-
- docFInfo.fdCreator = kMyDocCreator;
- docFInfo.fdType = kMyDocType;
-
- err = HSetFInfo(sfReply.sfFile.vRefNum, sfReply.sfFile.parID,
- sfReply.sfFile.name, &docFInfo);
- }
-
- // If we're successful in creating the file, set our document's FSSpec info, its
- // title and its window's title.
-
- if (err == noErr)
- err = ResError();
-
- if (err) return err;
-
- BlockMove(&sfReply.sfFile, docFSSpec, sizeof(FSSpec));
- BlockMove(&sfReply.sfFile.name, myDocument->documentTitle,
- (long) sfReply.sfFile.name[0] +1);
-
- SetWTitle(myDocument->documentWindow, myDocument->documentTitle);
- }
-
- // Open the file's data fork and resource fork.
-
- err = FSpOpenDF(docFSSpec, fsRdWrPerm, &dataRefNum);
-
- if (err == noErr)
- {
- resRefNum = HOpenResFile(docFSSpec->vRefNum, docFSSpec->parID,
- docFSSpec->name, fsRdWrPerm);
- err = ResError();
- }
-
- // Store the document's page-to-format correspondences, then flatten the
- // job to disk.
-
- if (err == noErr)
- {
- err = MySaveFormatRefs(myDocument);
-
- if (err == noErr)
- err = MySaveJobInDataFork(myDocument, dataRefNum);
- }
-
- if (err == noErr)
- {
-
- // Now write out the data for our document's pages.
-
- /*
- Place your application-specific code here to save
- other data associated with the document.
- .
- .
- .
- */
- }
-
- // Close the data and resource forks of this document.
-
- if (dataRefNum != -1) FSClose(dataRefNum);
- if (resRefNum != -1) CloseResFile(resRefNum);
- }
-
- UseResFile(oldResFile);
- return err;
- }
-
-
- // This routine is called to flatten a job to disk. We're passed
- // the refNum of the open data fork to write to.
-
- OSErr MySaveJobInDataFork(MyDocumentPtr myDocument, short dataRefNum)
- {
- OSErr err;
-
- // Reset the file's position to the beginning of the data fork, and
- // then write the flattened job there.
-
- err = SetFPos(dataRefNum, fsFromStart, 0);
-
- if (err == noErr)
- {
- GXFlattenJob(myDocument->documentJob,
- (gxPrintingFlattenProc) MyFlattenJobProc,
- (void *) dataRefNum);
-
- err = GXGetJobError(myDocument->documentJob);
- }
-
- return err;
- }
-
-
- // This routine is a PrintingFlattenProc which flattens a job
- // and writes it to the passed data fork.
-
- OSErr MyFlattenJobProc(long dataSize, void *data, void *dataRefNum)
- {
- long count = dataSize;
-
- return FSWrite((short) dataRefNum, &count, data);
- }
-
-
- // This routine is called to unflatten a job from disk. We're passed
- // the refNum of the open data fork to read from.
-
- OSErr MyLoadJobFromDataFork(MyDocumentPtr myDocument, short dataRefNum)
- {
- OSErr err;
-
- // Reset the file's position to the beginning of the data fork, and
- // then read and unflatten the job from there.
-
- err = SetFPos(dataRefNum, fsFromStart, 0);
-
- if (err == noErr)
- {
- GXUnflattenJob(myDocument->documentJob,
- (gxPrintingFlattenProc) MyUnflattenJobProc,
- (void *) dataRefNum);
-
- err = GXGetJobError(myDocument->documentJob);
- }
-
- return err;
- }
-
-
- // This routine is a PrintingFlattenProc which reads and unflattens
- // a job in the passed data fork.
-
- OSErr MyUnflattenJobProc(long dataSize, void *data, void *dataRefNum)
- {
- long count = dataSize;
-
- return FSRead((short) dataRefNum, &count, data);
- }
-
-
- // This routine opens a document and loads its previously saved job,
- // reassociating any formats that the job contains.
-
- OSErr MyOpenDocument(MyDocumentPtr myDocument)
- {
- OSErr err;
- Handle theJobData;
- short oldResFile, dataRefNum = -1, resRefNum = -1;
- StandardFileReply sfReply;
- SFTypeList myTypeList;
-
- // Let the user select a document to open.
-
- oldResFile = CurResFile();
-
- myTypeList[0] = kMyDocType;
- StandardGetFile(nil, 1, &myTypeList, &sfReply);
-
- if (!sfReply.sfGood)
- return noErr;
-
- // Open the selected file's data fork and resource fork.
-
- err = FSpOpenDF(&sfReply.sfFile, fsRdWrPerm, &dataRefNum);
-
- if (err == noErr)
- {
- resRefNum = HOpenResFile(sfReply.sfFile.vRefNum, sfReply.sfFile.parID,
- sfReply.sfFile.name, fsRdPerm);
- err = ResError();
- }
-
- // If we're successful in opening the file, set our document's FSSpec info, its
- // title, and its window's title.
-
- if (err == noErr)
- err = ResError();
-
- if (err) return err;
-
- BlockMove(&sfReply.sfFile, &myDocument->documentFSSpec, sizeof(FSSpec));
- BlockMove(&sfReply.sfFile.name, myDocument->documentTitle,
- (long) sfReply.sfFile.name[0] +1);
-
- SetWTitle(myDocument->documentWindow, myDocument->documentTitle);
-
- // If there's a job resource saved, load it and unflatten it.
-
- UseResFile(resRefNum);
- theJobData = Get1Resource(kMyJobType, kMyJobID);
-
- if (theJobData != nil)
- {
- GXUnflattenJobFromHdl(myDocument->documentJob, theJobData);
- err = GXGetJobError(myDocument->documentJob);
- ReleaseResource(theJobData);
- }
-
- // Set up the new format references for each page.
-
- if (err == noErr)
- err = MyAdjustFormats(myDocument);
-
- // Now load the data for our document's pages.
-
- /*
- Place your application-specific code here to load
- other data associated with the document.
- .
- .
- .
- */
-
- // Close the data and resource forks of this document.
-
- if (dataRefNum != -1) FSClose(dataRefNum);
- if (resRefNum != -1) CloseResFile(resRefNum);
-
- UseResFile(oldResFile);
- return err;
- }
-
-
- // This routine opens a document and loads its previously saved job
- // from the data fork, reassociating any formats that the job contains.
-
- OSErr MyOpenDocument2(MyDocumentPtr myDocument)
- {
- OSErr err;
- short oldResFile, dataRefNum = -1, resRefNum = -1;
- StandardFileReply sfReply;
- SFTypeList myTypeList;
-
- // Let the user select a document to open.
-
- oldResFile = CurResFile();
-
- myTypeList[0] = kMyDocType;
- StandardGetFile(nil, 1, &myTypeList, &sfReply);
-
- if (!sfReply.sfGood)
- return noErr;
-
- // Open the selected file's data fork and resource fork.
-
- err = FSpOpenDF(&sfReply.sfFile, fsRdWrPerm, &dataRefNum);
-
- if (err == noErr)
- {
- resRefNum = HOpenResFile(sfReply.sfFile.vRefNum, sfReply.sfFile.parID,
- sfReply.sfFile.name, fsRdPerm);
- err = ResError();
- }
-
- // If we're successful in opening the file, set our document's FSSpec info, its
- // title, and its window's title.
-
- if (err) return err;
-
- BlockMove(&sfReply.sfFile, &myDocument->documentFSSpec, sizeof(FSSpec));
- BlockMove(&sfReply.sfFile.name, myDocument->documentTitle,
- (long) sfReply.sfFile.name[0] +1);
-
- SetWTitle(myDocument->documentWindow, myDocument->documentTitle);
-
- // Load and unflatten the job from the data fork.
-
- err = MyLoadJobFromDataFork(myDocument, dataRefNum);
-
- if (err == noErr)
- {
-
- // Any format references saved with a document are no longer valid,
- // so we need to adjust them.
-
- UseResFile(resRefNum);
-
- if (err == noErr)
- err = MyAdjustFormats(myDocument);
-
- // Now load the data for our document's pages.
-
- /*
- Place your application-specific code here to load
- other data associated with the document.
- .
- .
- .
- */
-
- // Close the data and resource forks of this document.
-
- }
-
- if (dataRefNum != -1) FSClose(dataRefNum);
- if (resRefNum != -1) CloseResFile(resRefNum);
-
- UseResFile(oldResFile);
- return err;
- }
-
-
- // This routine opens a document and loads its previously saved job,
- // reassociating any formats that the job contains. It's just like
- // MyOpenDocument, but it opens the indicated file and doesn't
- // present a file dialog.
-
- OSErr MyFSOpenDocument(MyDocumentPtr myDocument, FSSpec *docFSSpec)
- {
- OSErr err;
- Handle theJobData;
- short oldResFile, dataRefNum = -1, resRefNum = -1;
-
- oldResFile = CurResFile();
-
- // Open the selected file's data fork and resource fork.
-
- err = FSpOpenDF(docFSSpec, fsRdWrPerm, &dataRefNum);
-
- if (err == noErr)
- {
- resRefNum = HOpenResFile(docFSSpec->vRefNum, docFSSpec->parID, docFSSpec->name, fsRdPerm);
- err = ResError();
- }
-
- // If we're successful in opening the file, set our document's FSSpec info, its
- // title, and its window's title.
-
- if (err == noErr)
- err = ResError();
-
- if (err) return err;
-
- BlockMove(docFSSpec, &myDocument->documentFSSpec, sizeof(FSSpec));
- BlockMove(docFSSpec->name, myDocument->documentTitle, (long) docFSSpec->name[0] +1);
- SetWTitle(myDocument->documentWindow, myDocument->documentTitle);
-
- // If there's a job resource saved, load it and unflatten it.
-
- UseResFile(resRefNum);
- theJobData = Get1Resource(kMyJobType, kMyJobID);
-
- if (theJobData != nil)
- {
- GXUnflattenJobFromHdl(myDocument->documentJob, theJobData);
- err = GXGetJobError(myDocument->documentJob);
- ReleaseResource(theJobData);
- }
-
- // Any format references saved with a document are no longer valid,
- // so we need to adjust them.
-
- if (err == noErr)
- err = MyAdjustFormats(myDocument);
-
- // Now load the data for our document's pages.
-
- /*
- Place your application-specific code here to load
- other data associated with the document.
- .
- .
- .
- */
-
- // Close the data and resource forks of this document.
-
- if (dataRefNum != -1) FSClose(dataRefNum);
- if (resRefNum != -1) CloseResFile(resRefNum);
-
- UseResFile(oldResFile);
- return err;
- }
-
-
- // This routine saves page format indices for a document. We'll store
- // this info in the job's default format's collection. We use this
- // information to "reconstruct" the document the next time we
- // open it. This routine is called when we save a document, before we
- // have flattened the document's job.
- //
-
- OSErr MySaveFormatRefs(MyDocumentPtr myDocument)
- {
- OSErr err = noErr;
- Handle theFormatIdxList;
- Collection fmtCollection;
- gxFormat defaultFmt;
-
- // If we have any pages in this document, create a handle containing all of the
- // page format indices.
-
- if (myDocument->numPages > 0)
- {
-
- // Get the job's default format's collection, and if we've already
- // stored a page-to-format correspondence item in it, remove it.
-
- defaultFmt = GXGetJobFormat(myDocument->documentJob, 1);
- fmtCollection = GXGetFormatCollection(defaultFmt);
-
- if (fmtCollection != nil)
- RemoveCollectionItem(fmtCollection, kMyFormatInfoType, kMyFormatInfoTagID);
-
- // Create a list of page-to-format correspondences for the current document.
- // If there are no errors, add the item to the job's default format's
- // collection, for later retrieval.
-
-
- err = MyCreateFormatIndexList(myDocument, &theFormatIdxList);
-
- if (err == noErr)
- {
- HLock(theFormatIdxList);
- err = AddCollectionItem(fmtCollection,
- kMyFormatInfoType,
- kMyFormatInfoTagID,
- GetHandleSize(theFormatIdxList),
- *theFormatIdxList);
-
- DisposHandle(theFormatIdxList);
- }
- }
-
- return err;
- }
-
-
- // This routine stores the index of each page's format in a handle.
- // The index of page #1's format will go in the first longword of
- // theFormatIdxList handle, the index of the next page's format will
- // go in the next longword, and so on. The handle is created and
- // returned to the caller.
-
- OSErr MyCreateFormatIndexList(MyDocumentPtr myDocument, Handle *theFormatIdxList)
- {
- OSErr err;
- long fmtIdx, pg, *idxList;
- gxFormat curFormat;
-
- // Create a handle large enough to hold all of our entries. We use
- // NewHandleClear so that all of our indices are initialized to 0
- // (an invalid format index). Since our application stores a nil
- // format reference for any page which uses the job's default format,
- // this allows us to indicate these "nil references" by an index of
- // 0 in our collection item. When we re-open the document, we'll
- // know that an index of 0 means "Use the job's default format."
-
- *theFormatIdxList = NewHandleClear(sizeof(long) * (myDocument->numPages));
- err = MemError();
-
- // If there aren't any errors, go through every format in the document's
- // job. If the format is used by any pages of our document, store the
- // format's index in those page entries of theFormatIdxList. We skip format
- // #1, since that's the job format (and we're storing nil for the index in
- // this case). Because we created the handle with NewHandleClear, nil will
- // already be stored in any entries we don't change.
-
- if (err == noErr)
- {
- HLock(*theFormatIdxList);
- idxList = (long *) **theFormatIdxList;
-
- for (fmtIdx = 2; fmtIdx <= GXCountJobFormats(myDocument->documentJob); fmtIdx++)
- {
- curFormat = GXGetJobFormat(myDocument->documentJob, fmtIdx);
-
- for (pg = 1; pg <= myDocument->numPages; pg++)
- if (myDocument->pageFormat[pg -1] == curFormat)
- idxList[pg -1] = fmtIdx;
- }
-
- HUnlock(*theFormatIdxList);
- }
-
- return err;
- }
-
-
- // This routine associates new format references with a document, based
- // upon the format indices which were saved with the document.
- // The routine is called when we open a document.
- //
- // The format references will be stored in the passed MyDocumentRec
- // structure.
-
- OSErr MyAdjustFormats(MyDocumentPtr myDocument)
- {
- OSErr err = noErr;
- Handle theFormatIdxList = nil;
- gxFormat theFormat, defaultFmt;
- long pg, numPages, fmtIdx, *idxList, idx, listSize, attribs;
- Collection fmtCollection;
-
- // Get the job's default format's collection, and look for one of our
- // page-to-format correspondence items in it.
-
- defaultFmt = GXGetJobFormat(myDocument->documentJob, 1);
- fmtCollection = GXGetFormatCollection(defaultFmt);
-
-
- // Load our item containing our page-to-format correspondences.
- // We do this in two passes. First we determine if the item
- // exists, and if so, get its size. Next we create a handle
- // to hold the item (if it exists), and then actually retrieve it.
- // Because there will be one longword entry for each page of our
- // document, we can determine the number of pages in the document.
-
- err = GetCollectionItemInfo(fmtCollection, kMyFormatInfoType,
- kMyFormatInfoTagID, &idx, &listSize, &attribs);
-
- if (err == noErr)
- theFormatIdxList = NewHandle(listSize);
-
- if (theFormatIdxList != nil)
- {
- HLock(theFormatIdxList);
-
- err = GetCollectionItem(fmtCollection, kMyFormatInfoType,
- kMyFormatInfoTagID, nil, *theFormatIdxList);
-
- numPages = listSize / sizeof(long);
-
-
- // We TEMPORARILY cheat here and rebuild the page rather than load and save the shapes.
-
- for (pg = 1; !err && (pg <= numPages); pg++)
- {
- err = MyInsertPage(myDocument);
- myDocument->curPage = pg;
- }
- myDocument->curPage = 1;
-
- // Loop through each saved index. The way we saved them, the first is for
- // page 1, the second is for page 2, and so on. We need to call
- // GetJobFormat for each saved index. If the index is nil, that's just
- // our way of saying "use the job format." In that case, we don't call
- // GetJobFormat, we just store nil for the page's format. Store
- // the format references as they're processed. When we're done, throw
- // away the handle we created.
-
- idxList = (long *) *theFormatIdxList;
-
- for (pg = 1; pg <= numPages; pg++)
- {
- fmtIdx = idxList[pg -1];
-
- if (fmtIdx != nil)
- theFormat = GXGetJobFormat(myDocument->documentJob, fmtIdx);
- else
- theFormat = nil;
-
- myDocument->pageFormat[pg -1] = theFormat;
- }
-
- DisposHandle(theFormatIdxList);
- }
-
- return err;
- }
-
-
- // This routine converts an old-style (TPrint) print record into a QuickDraw
- // GX job. We use this routine when we're opening an old document that
- // had a print record saved with it rather than a job. The old-style
- // print record is passed in hPrint.
-
- OSErr MyPrintRecordToJob(MyDocumentPtr myDocument, THPrint hPrint)
- {
-
- // Convert the print record and store its settings in
- // the passed job. Then dispose of its handle.
-
- GXConvertPrintRecord(myDocument->documentJob, hPrint);
- DisposeHandle((Handle) hPrint);
-
- return GXGetJobError(myDocument->documentJob);
- }
-
-
- // Insert a page at the current display location.
-
- OSErr MyInsertPage(MyDocumentPtr myDocument)
- {
- gxGraphicsError grErr;
- long pg, curPage;
- Str255 pStr;
- gxRectangle windowBounds;
- gxShape txtShape;
-
- curPage = myDocument->curPage;
-
- if (myDocument->numPages != 0)
- for (pg = myDocument->numPages; pg > curPage; pg--)
- {
- myDocument->documentPage[pg] = myDocument->documentPage[pg -1];
- myDocument->pageFormat[pg] = myDocument->pageFormat[pg -1];
- }
- else
- curPage = 0;
-
- ++curPage;
-
- pStr[0] = sprintf(&pStr[1], "%s%i", "Reference ID #", myDocument->numPages +1);
- txtShape = GXNewText((long) pStr[0], (const unsigned char *) &pStr[1], nil);
-
- SetShapeCommonFont(txtShape, timesFont);
- GXSetShapeTextSize(txtShape, ff(24));
- GXSetShapeAttributes(txtShape, (GXGetShapeAttributes(txtShape)) | gxMapTransformShape);
- GXSetShapeViewPorts(txtShape, 1, &myDocument->documentViewPort);
-
- windowBounds.left = ff(0);
- windowBounds.top = ff(0);
- windowBounds.right = ff(370);
- windowBounds.bottom = ff(440);
-
- CenterShape(txtShape, &windowBounds);
- myDocument->documentPage[curPage -1] = GXNewShape(gxPictureType);
- GXSetShapeViewPorts(myDocument->documentPage[curPage -1], 1, &myDocument->documentViewPort);
- GXSetShapeAttributes(myDocument->documentPage[curPage -1],
- (GXGetShapeAttributes(myDocument->documentPage[curPage -1])) | gxUniqueItemsShape);
- GXSetPictureParts(myDocument->documentPage[curPage -1], 0, 0, 1, &txtShape, nil, nil, nil);
- GXDisposeShape(txtShape);
-
- myDocument->pageFormat[curPage -1] = nil;
-
- grErr = GXGetGraphicsError(nil);
-
- if (grErr == noErr)
- {
- myDocument->curPage = curPage;
- ++myDocument->numPages;
- InvalRect(&(myDocument->documentWindow)->portRect);
- }
- else
- GXDisposeShape(myDocument->documentPage[curPage -1]);
-
- return (OSErr) grErr;
- }
-
-
- // Delete the current page of a document and free up any memory we
- // allocated for it.
-
- OSErr MyDeletePage(MyDocumentPtr myDocument)
- {
- OSErr err;
- long curPage, pg;
-
- // Dispose of the current page's shape and format. If the page format is nil,
- // this indicates that the page used the document's job format. In this case,
- // there is no format to dispose.
-
- curPage = myDocument->curPage;
- GXDisposeShape(myDocument->documentPage[curPage -1]);
-
- if (myDocument->pageFormat[curPage -1] != nil)
- GXDisposeFormat(myDocument->pageFormat[curPage -1]);
-
- /*
- Place any application-specific code to delete a page here.
-
- .
- .
- .
-
- */
-
- // We shift all pages after this one down a page to fill the gap created
- // by this deletion. When finished, we decrement the number of pages in
- // our document.
-
- if (myDocument->numPages != 0)
- for (pg = curPage; pg < myDocument->numPages; pg++)
- {
- myDocument->documentPage[pg -1] = myDocument->documentPage[pg];
- myDocument->pageFormat[pg -1] = myDocument->pageFormat[pg];
- }
-
- --myDocument->numPages;
-
- // If the "current page" value is now invalid for this document, decrement it to
- // reference the previous page, if any. Invalidate the window so that the document
- // is updated on screen. Finally, check for errors and return.
-
- if (curPage > myDocument->numPages)
- --myDocument->curPage;
-
- InvalRect(&(myDocument->documentWindow)->portRect);
-
- err = GXGetJobError(myDocument->documentJob);
- if (err == noErr) err = GXGetGraphicsError(nil);
-
- return err;
- }
-
-
- // MyBackPage moves us back a page in the document.
-
- void MyBackPage(WindowPtr whichWindow)
- {
- MyDocumentPtr myDocument;
-
- if (((WindowPeek) whichWindow)->windowKind != userKind) return;
- myDocument = (MyDocumentPtr) GetWRefCon(whichWindow);
-
- if (myDocument->curPage > 1)
- {
- --myDocument->curPage;
- InvalRect(&whichWindow->portRect);
- }
- }
-
-
- // MyAheadPage moves us forward a page in the document.
-
- void MyAheadPage(WindowPtr whichWindow)
- {
- MyDocumentPtr myDocument;
-
- if (((WindowPeek) whichWindow)->windowKind != userKind) return;
- myDocument = (MyDocumentPtr) GetWRefCon(whichWindow);
-
- if (myDocument->curPage < myDocument->numPages)
- {
- ++myDocument->curPage;
- InvalRect(&whichWindow->portRect);
- }
- }
-
-
- // This routine adds a form consisting of a rectangle
- // to the current page's format.
-
- OSErr MyAddFormatForm(MyDocumentPtr myDocument)
- {
- OSErr err;
- long curPage;
- gxFormat theFormat;
- gxShape rectShape;
- gxRectangle pageRect;
-
- // Get the current format. If it's nil, this means we're
- // using the job's default format.
-
- curPage = myDocument->curPage;
- theFormat = myDocument->pageFormat[curPage -1];
-
- if (theFormat == nil)
- theFormat = GXGetJobFormat(myDocument->documentJob, 1);
-
- // Create a rectangle shape to use as the format's form.
- // We'll make the rectangle's frame be the imageable area
- // of the page.
-
- GXGetFormatDimensions(theFormat, &pageRect, nil);
- rectShape = GXNewRectangle(&pageRect);
-
- GXSetShapeBounds(rectShape, &pageRect);
- GXSetShapePen(rectShape, ff(3));
- GXInsetShape(rectShape, ff(3));
- GXSetShapeFill(rectShape, gxClosedFrameFill);
-
- err = (OSErr) GXGetGraphicsError(nil);
-
- // Set the format's form to our new shape (it must be a
- // picture), check for errors, then dispose of the shape.
-
- if (err == noErr)
- {
- GXSetShapeType(rectShape, gxPictureType);
- GXSetFormatForm(theFormat, rectShape, nil);
- err = GXGetJobError(myDocument->documentJob);
- }
-
- GXDisposeShape(rectShape);
-
- return err;
- }
-
-
- // This routine removes the current page's format form, if any.
-
- OSErr MyRemoveFormatForm(MyDocumentPtr myDocument)
- {
- long curPage;
- gxFormat theFormat;
-
- // Get the current format. If it's nil, this means we're
- // using the job's default format.
-
- curPage = myDocument->curPage;
- theFormat = myDocument->pageFormat[curPage -1];
-
- if (theFormat == nil)
- theFormat = GXGetJobFormat(myDocument->documentJob, 1);
-
- // Set the format's form and mask to nil.
-
- GXSetFormatForm(theFormat, nil, nil);
- return GXGetJobError(myDocument->documentJob);
- }
-
-
- // This routine moves a page format to another job. We use this routine
- // when we move a page from one document to another, if no other page in
- // the original document currently uses the source page's format.
- //
- // srcPage and srcDocument represent the page's location in the original
- // document, destPage and destDocument refer to the new location and
- // document. There is initially no page format for the destination page.
-
- OSErr MyMoveFormatToJob(long srcPage, MyDocumentPtr srcDocument, long destPage, MyDocumentPtr destDocument)
- {
- OSErr err;
- gxFormat srcPgFormat, destPgFormat;
-
- // Get the indicated source page format. If the reference is nil, this
- // indicates that we're using the source document's default job format.
- // In this case, create a destination format from the source job and
- // use that.
-
- srcPgFormat = srcDocument->pageFormat[srcPage];
-
- if (srcPgFormat == nil)
- srcPgFormat = GXNewFormat(srcDocument->documentJob);
-
- // Create a new destination format and copy the source format to it. When
- // done, dispose of the source format and clear out the source page's reference.
-
- destPgFormat = GXNewFormat(destDocument->documentJob);
- GXCopyFormat(srcPgFormat, destPgFormat);
- GXDisposeFormat(srcPgFormat);
- srcDocument->pageFormat[srcPage] = nil;
-
- // If there were no errors, store the destination page's format reference.
-
- err = GXGetJobError(srcDocument->documentJob);
-
- if (err == noErr)
- err = GXGetJobError(destDocument->documentJob);
-
- if (err == noErr)
- destDocument->pageFormat[destPage] = destPgFormat;
-
- return err;
- }
-
-
- // This function takes the job associated with srcDocument and copies
- // its information to destDocument. This has the effect of copying
- // the formatting and job-specific information in the source document
- // to the destination document.
- //
- // Note that this changes any formats that the destination job
- // originally had (and the old references become invalid).
-
- OSErr MyCopyJobToDoc(MyDocumentPtr srcDocument, MyDocumentPtr destDocument)
- {
- long pg;
-
- // Copy the job information, invalidate any old format references,
- // and return any error codes.
-
- GXCopyJob(srcDocument->documentJob, destDocument->documentJob);
-
- for (pg = 1; pg <= destDocument->numPages; pg++)
- destDocument->pageFormat[pg -1] = nil;
-
- return GXGetJobError(srcDocument->documentJob);
- }
-
-
- // This routine stores a refCon in the job, and then retrieves it.
- // we compare the 2 values to see if they're the same, which they'd
- // better be.
-
- OSErr MyJobRefConTest(MyDocumentPtr myDocument)
- {
- Str255 pStr;
- MyDocumentPtr beforePtr, afterPtr;
-
- // Store the document pointer, set the refCon field, retrieve the refCon,
- // and compare the two values.
-
- beforePtr = myDocument;
- GXSetJobRefCon(myDocument->documentJob, myDocument);
- afterPtr = GXGetJobRefCon(myDocument->documentJob);
-
- pStr[0] = sprintf(&pStr[1], "These better be the same… %p == %p?", beforePtr, afterPtr);
- MyDisplayInfo(pStr);
-
- return GXGetJobError(myDocument->documentJob);
- }
-
-
- // This function returns the number of pages in the indicated
- // print file.
-
- OSErr MyGetPrintFilePages(FSSpec *printFSSpec, long *numCopies)
- {
- OSErr err;
- gxPrintFile thePrintFile;
- gxJob fileJob;
-
- // Create a new job for GXOpenPrintFile, then open the print file, get the
- // number of pages in it, close it, and check for errors. Finally,
- // dispose of the temporary job we created and return.
-
- err = GXNewJob(&fileJob);
-
- if (err == noErr)
- {
- thePrintFile = GXOpenPrintFile(fileJob, printFSSpec, fsCurPerm);
- *numCopies = GXCountPrintFilePages(thePrintFile);
- GXClosePrintFile(thePrintFile);
-
- err = GXGetJobError(fileJob);
- GXDisposeJob(fileJob);
- }
-
- return err;
- }
-
-
- // This routine reads a page from a print file and returns its
- // corresponding format and shape.
-
- OSErr MyReadPrintFilePage(MyDocumentPtr myDocument, FSSpec *printFSSpec,
- long whichPg, gxFormat *pgFormat, gxShape *pgShape)
- {
- gxPrintFile thePrintFile;
-
- // Open the print file, read the page, close the file, and check for errors.
-
- thePrintFile = GXOpenPrintFile(myDocument->documentJob, printFSSpec, fsCurPerm);
- GXReadPrintFilePage(thePrintFile, whichPg, 1, &myDocument->documentViewPort, pgFormat, pgShape);
- GXClosePrintFile(thePrintFile);
-
- return GXGetJobError(myDocument->documentJob);
- }
-
-
- // This routine creates a new paperType based on the job passed.
-
- OSErr MyCreatePaperType(MyDocumentPtr myDocument, Str31 paperName, gxRectangle *pageSize,
- gxRectangle *paperSize, gxPaperType *newPaperType)
- {
- *newPaperType = GXNewPaperType(myDocument->documentJob, paperName, pageSize, paperSize);
-
- return GXGetJobError(myDocument->documentJob);
- }
-
-
- // This is a FormatProc that looks at the mapping of each format
- // it's passed.
-
- pascal gxLoopStatus MyCheckMappingProc(gxFormat aFormat, void *theMapping)
- {
-
- // Get the mapping for the current format, check it out,
- // and keep looping until all formats have been accessed.
-
- GXGetFormatMapping(aFormat, (gxMapping *) theMapping);
-
- /* Below, your application could adjust rulers, or do some
- other useful thing based on each format's mapping.
- .
- .
- .
- */
-
- return gxKeepLooping;
- }
-
-
- // This routine passes the format of each page in our
- // document to the "MyCheckMappingProc" FormatProc.
-
- OSErr MyCheckAllFormatMappings(MyDocumentPtr myDocument)
- {
- gxMapping theMapping;
-
- // Loop through each format, and check its mapping.
-
- GXForEachJobFormatDo(myDocument->documentJob, MyCheckMappingProc,
- (void *) &theMapping);
-
- return GXGetJobError(myDocument->documentJob);
- }
-
-
- // This routine returns the format mapping for the indicated
- // page of our document.
-
- OSErr MyGetFormatMapping(MyDocumentPtr myDocument, long whichPage,
- gxMapping *theMapping)
- {
- gxFormat pgFormat;
-
- // Get the current page's format, or the job's default
- // format if we've set this page's format reference to nil
- // to indicate this.
-
- pgFormat = myDocument->pageFormat[whichPage -1];
-
- if (pgFormat == nil)
- pgFormat = GXGetJobFormat(myDocument->documentJob, 1);
-
- // Get the format's mapping.
-
- GXGetFormatMapping(pgFormat, theMapping);
- return GXGetJobError(myDocument->documentJob);
- }
-
-
- // This function returns the current "copies" setting from a document's
- // job. A user sets this value via the print dialog, and it sticks to
- // the job, once set.
- //
- // In the passed document's job, we look for a copiesTag collection
- // item. If we find one, we return the number of copies stored in it.
-
- OSErr MyGetJobCopies(MyDocumentPtr myDocument, short *numCopies)
- {
- OSErr err;
- Collection jobCollection;
- gxCopiesInfo theCopiesInfo;
-
- // Get the job collection, and then look for a copiesTag collection item.
-
- jobCollection = GXGetJobCollection(myDocument->documentJob);
-
- err = GetCollectionItem(jobCollection,
- gxCopiesTag,
- gxPrintingTagID,
- nil,
- &theCopiesInfo);
-
- // If we found one, extract the number of copies and return it.
-
- if (err == noErr)
- *numCopies = theCopiesInfo.copies;
-
- return err;
- }
-
-
- // This function displays a dialog showing the name and type of the
- // printer and printer driver that the passed document's job will
- // print to.
-
- OSErr MyShowJobPrinterInfo(MyDocumentPtr myDocument)
- {
- OSErr err;
- short itemHit;
- DialogPtr msgDlog;
- GrafPtr oldPort;
- gxPrinter jobPrinter;
- OSType deviceOSType, driverOSType;
- Str255 deviceName, deviceType, driverName, driverType;
-
- // Load our info dialog.
-
- GetPort(&oldPort);
- msgDlog = GetNewDialog(r_printerInfoDlog, nil, (WindowPtr) -1);
- err = ResError();
-
- // Get the current printer for this job. From that, get the
- // current device name, driver name, device type, and driver type.
-
- if (err == noErr)
- {
- jobPrinter = GXGetJobOutputPrinter(myDocument->documentJob);
-
- GXGetPrinterName(jobPrinter, deviceName);
- GXGetPrinterDriverName(jobPrinter, driverName);
- deviceOSType = GXGetPrinterType(jobPrinter);
- driverOSType = GXGetPrinterDriverType(jobPrinter);
-
- err = GXGetJobError(myDocument->documentJob);
-
- // Since the device and driver type are OSTypes, we need to convert them to
- // Pascal strings for ParamText. That's what these two lines do.
-
- if (err == noErr)
- {
- BlockMove(&deviceOSType, &deviceType[1], (long) (deviceType[0] = 4));
- BlockMove(&driverOSType, &driverType[1], (long) (driverType[0] = 4));
-
- // Use ParamText to pass the data to our dialog, then display our dialog
- // and set our current port to it.
-
- ParamText(deviceName, driverName, deviceType, driverType);
- SetPort(msgDlog);
- MyPositionWindow(msgDlog, true, n_dlogLevel);
-
- // Loop until the user clicks "OK", then reset ParamText and dispose
- // of our dialog.
-
- do
- {
- ModalDialog(nil, &itemHit);
- }
- while (itemHit != kOKButton);
-
- ParamText("\p", "\p", "\p", "\p");
- DisposDialog(msgDlog);
- }
- }
-
- SetPort(oldPort);
- return err;
- }
-
-
- // This function displays a dialog showing the highest
- // "square" resolutions for the job's formatting and
- // output printers.
-
- void MyShowJobPrinterResolution(MyDocumentPtr myDocument)
- {
- fixed hFRes, vFRes, hORes, vORes;
- Str255 pStr;
-
- MyGetFormatDeviceResolution(myDocument->documentJob, &hFRes, &vFRes);
- MyGetOutputDeviceResolution(myDocument->documentJob, &hORes, &vORes);
-
- pStr[0] = sprintf(&pStr[1], "%s%d%s%d%s",
- "Formatting printer's res. = ",
- FixedToInt(hFRes),
- " dpi.\n Output printer's res. = ",
- FixedToInt(hORes),
- " dpi.");
-
- MyDisplayInfo(pStr);
- }
-
-
- // This routine returns the highest square resolution of
- // the formatting printer for the specified job.
-
- void MyGetFormatDeviceResolution(gxJob whichJob, fixed *hRes, fixed *vRes)
- {
- gxPrinter formatPrinter;
- long numViewDevices, idx;
- gxViewDevice printerVDev;
- gxMapping vDevMapping;
-
- /*
- Get the formatting printer, and the number of
- viewdevices for that printer.
- */
-
- *hRes = 0;
- *vRes = 0;
-
- formatPrinter = GXGetJobFormattingPrinter(whichJob);
- numViewDevices = GXCountPrinterViewDevices(formatPrinter);
-
- /*
- Loop through the viewdevices that this printer supports,
- and get the highest "square" (vertical == horizontal)
- resolution.
- */
-
- for (idx = 1; idx <= numViewDevices; idx++)
- {
- printerVDev = GXGetPrinterViewDevice(formatPrinter, idx);
- GXGetViewDeviceMapping(printerVDev, &vDevMapping);
-
- if ((vDevMapping.map[0][0] == vDevMapping.map[1][1]) &&
- (vDevMapping.map[0][0] > *hRes) && (vDevMapping.map[1][1] > *vRes))
- {
- *hRes = vDevMapping.map[0][0];
- *vRes = vDevMapping.map[1][1];
- }
- }
-
- /*
- We have only scaling factors (multiples of 72 dpi),
- so convert them into resolutions.
- */
-
- *hRes = FixedMultiply(*hRes, ff(72));
- *vRes = FixedMultiply(*vRes, ff(72));
- }
-
-
- // This routine returns the highest square resolution of
- // the output printer for the specified job.
-
- void MyGetOutputDeviceResolution(gxJob whichJob, fixed *hRes, fixed *vRes)
- {
- gxPrinter outputPrinter;
- long numViewDevices, idx;
- gxViewDevice printerVDev;
- gxMapping vDevMapping;
-
- /*
- Get the output printer, and the number of
- viewdevices for that printer.
- */
-
- *hRes = 0;
- *vRes = 0;
-
- outputPrinter = GXGetJobOutputPrinter(whichJob);
- numViewDevices = GXCountPrinterViewDevices(outputPrinter);
-
- /*
- Loop through the viewdevices that this printer supports,
- and get the highest "square" (vertical == horizontal)
- resolution.
- */
-
- for (idx = 1; idx <= numViewDevices; idx++)
- {
- printerVDev = GXGetPrinterViewDevice(outputPrinter, idx);
- GXGetViewDeviceMapping(printerVDev, &vDevMapping);
-
- if ((vDevMapping.map[0][0] == vDevMapping.map[1][1]) &&
- (vDevMapping.map[0][0] > *hRes) && (vDevMapping.map[1][1] > *vRes))
- {
- *hRes = vDevMapping.map[0][0];
- *vRes = vDevMapping.map[1][1];
- }
- }
-
- /*
- We have only scaling factors (multiples of 72 dpi),
- so convert them into resolutions.
- */
-
- *hRes = FixedMultiply(*hRes, ff(72));
- *vRes = FixedMultiply(*vRes, ff(72));
- }
-
-
- // This routine returns the name of the paperType
- // used by the current page of a document.
-
- OSErr MyGetPaperTypeName(MyDocumentPtr myDocument, Str255 paperTypeName)
- {
- gxPaperType thePaperType;
- long curPage;
- gxFormat pgFormat;
-
- // Get the format for the current page. If the format is nil,
- // this indicates that we should use the job's default format.
-
- curPage = myDocument->curPage;
- pgFormat = myDocument->pageFormat[curPage -1];
-
- if (pgFormat == nil)
- pgFormat = GXGetJobFormat(myDocument->documentJob, 1);
-
- // Get the format's paperType and the paperType's name.
-
- thePaperType = GXGetFormatPaperType(pgFormat);
- GXGetPaperTypeName(thePaperType, paperTypeName);
-
- return GXGetJobError(myDocument->documentJob);
- }
-
-
- // This routine returns the dimensions of the page and
- // paper areas of the paperType used by the current
- // page of a document.
-
- OSErr MyGetPaperTypeDims(MyDocumentPtr myDocument,
- gxRectangle *pageBounds, gxRectangle *paperBounds)
- {
- gxPaperType thePaperType;
- long curPage;
- gxFormat pgFormat;
-
- // Get the format for the current page. If the format is nil,
- // this indicates that we should use the job's default format.
-
- curPage = myDocument->curPage;
- pgFormat = myDocument->pageFormat[curPage -1];
-
- if (pgFormat == nil)
- pgFormat = GXGetJobFormat(myDocument->documentJob, 1);
-
- // Get the format's paperType and the paperType's bounds.
- // Note that you could also use GXGetFormatDimensions to do this.
-
- thePaperType = GXGetFormatPaperType(pgFormat);
- GXGetPaperTypeDimensions(thePaperType, pageBounds, paperBounds);
-
- return GXGetJobError(myDocument->documentJob);
- }
-
-
- // This routine displays information about every
- // paperType in a document's job which can be
- // used on the document's current output device.
-
- OSErr MyListAllPaperTypes(MyDocumentPtr myDocument)
- {
- GXForEachJobPaperTypeDo(myDocument->documentJob, (gxPaperTypeProc) MyPTInfoProc, nil, false);
- return GXGetJobError(myDocument->documentJob);
- }
-
-
- // This routine is a paperType procedure. It displays
- // the name and dimensions of the paperType passed.
-
- pascal gxLoopStatus MyPTInfoProc(gxPaperType thePaperType, void *refCon)
- {
- gxRectangle pageBounds, paperBounds;
- Str255 pStr1, pStr2;
- char *pStr1Ptr;
-
- #pragma unused(refCon);
-
- // Get the paperType's name.
-
- GXGetPaperTypeName(thePaperType, pStr1);
- pStr1[pStr1[pStr1[0]]] = 0;
- pStr1Ptr = &pStr1[1];
-
-
- // Get the paperType's dimensions.
-
- GXGetPaperTypeDimensions(thePaperType, &pageBounds, &paperBounds);
- pStr2[0] = sprintf(&pStr2[1], "%s: %s %i, %i, %i, %i. %s %i, %i, %i, %i.",
- pStr1Ptr,
- "\npageBounds =",
- pageBounds.top >>16,
- pageBounds.left >>16,
- pageBounds.bottom >>16,
- pageBounds.right >>16,
- "\npaperBounds =",
- paperBounds.top >>16,
- paperBounds.left >>16,
- paperBounds.bottom >>16,
- paperBounds.right >>16);
-
- MyDisplayInfo(pStr2);
-
- // Keep looping until all papertypes have been accessed.
-
- return gxKeepLooping;
- }
-
-
- // This routine displays an "About…" dialog.
-
- void MyDisplayAbout()
- {
- short oldResFile, theItem;
- DialogPtr theDialog;
- GrafPtr oldPort;
-
- oldResFile = CurResFile();
- UseResFile(gAppResRefNum);
-
- theDialog = GetNewDialog(r_aboutDlog, nil, (WindowPtr) -1);
-
- if (theDialog)
- {
- GetPort(&oldPort);
- SetPort(theDialog);
- MyPositionWindow(theDialog, true, n_dlogLevel);
-
- do
- {
- ModalDialog(nil, &theItem);
- }
- while (theItem != kOKButton);
-
- SetPort(oldPort);
- DisposeDialog(theDialog);
- }
-
- UseResFile(oldResFile);
- }
-
-
- // This routine displays a dialog with a message and an "OK"
- // button in it. When the user clicks OK, the dialog is disposed.
- // We use this routine to show information to the user using a
- // means more friendly than the DebugStr calls we used to make.
-
- void MyDisplayInfo(Str255 msg)
- {
- short oldResFile, itemType, theItem;
- Handle itemHdl;
- Rect itemRect;
- DialogPtr theDialog;
- GrafPtr oldPort;
-
- oldResFile = CurResFile();
- UseResFile(gAppResRefNum);
-
- theDialog = GetNewDialog(r_msgDlog, nil, (WindowPtr) -1);
-
- if (theDialog)
- {
- GetPort(&oldPort);
- SetPort(theDialog);
-
- GetDItem(theDialog, d_msgItem, &itemType, &itemHdl, &itemRect);
- SetIText(itemHdl, msg);
- MyPositionWindow(theDialog, true, n_dlogLevel);
-
- do
- {
- ModalDialog(nil, &theItem);
- }
- while (theItem != kOKButton);
-
- SetPort(oldPort);
- DisposeDialog(theDialog);
- }
-
- UseResFile(oldResFile);
- }
-
-
- // This routine positions a window on the screen, centered
- // horizontally and positioned vertPercent down the current
- // screen. If showIt is true, we make the window visible,
- // otherwise we hide it.
-
- void MyPositionWindow(WindowPtr windPtr, Boolean showIt, float vertPercent)
- {
- Rect devRect;
- short amtFromTop, windWidth, deviceWidth;
- GDHandle curGDH;
-
- // Get the current GDevice and use its bounds to calculate where we
- // should move the window to.
-
- if (windPtr != nil)
- {
- curGDH = GetGDevice();
- devRect = (*curGDH)->gdRect;
-
- amtFromTop = (devRect.bottom - devRect.top +1) * vertPercent;
- windWidth = windPtr->portRect.right - windPtr->portRect.left +1;
- deviceWidth = devRect.right - devRect.left +1;
-
-
- // Hide the window, move it, and (if we're supposed to) show it again.
-
- ShowHide(windPtr, false);
- MoveWindow(windPtr, devRect.left + (deviceWidth /2 - windWidth /2), devRect.top + amtFromTop, true);
- if (showIt) ShowHide(windPtr, true);
- }
- }
-
-
- //------ main -------------------------------------------------------------
-
- main()
- {
- OSErr err;
- gxGraphicsClient client;
- short i;
-
- MaxApplZone();
- for (i=1; i<=4; i++) MoreMasters();
-
- client = GXNewGraphicsClient(nil, 400 * 1024, nil);
- err = MyInitializeApp();
-
- GXEnterGraphics();
- err = GXInitPrinting();
-
- if (!err) MyEventLoop();
-
- err = GXExitPrinting();
- GXExitGraphics();
- GXDisposeGraphicsClient(client);
- }
-